blob: 0946ba27cc1aee879ea0563b235648510c75e387 [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
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700291 // This is a process with a heavy-weight application. It is in the
292 // background, but we want to try to avoid killing it. Value set in
293 // system/rootdir/init.rc on startup.
294 static final int HEAVY_WEIGHT_APP_ADJ;
295
296 // This is a process only hosting components that are perceptible to the
297 // user, and we really want to avoid killing them, but they are not
298 // immediately visible. An example is background music playback. Value set in
299 // system/rootdir/init.rc on startup.
300 static final int PERCEPTIBLE_APP_ADJ;
301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 // This is a process only hosting activities that are visible to the
303 // user, so we'd prefer they don't disappear. Value set in
304 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800305 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306
307 // This is the process running the current foreground app. We'd really
308 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800309 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310
311 // This is a process running a core server, such as telephony. Definitely
312 // don't want to kill it, but doing so is not completely fatal.
313 static final int CORE_SERVER_ADJ = -12;
314
315 // The system process runs at the default adjustment.
316 static final int SYSTEM_ADJ = -16;
317
318 // Memory pages are 4K.
319 static final int PAGE_SIZE = 4*1024;
320
321 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800322 static final int EMPTY_APP_MEM;
323 static final int HIDDEN_APP_MEM;
324 static final int HOME_APP_MEM;
325 static final int BACKUP_APP_MEM;
326 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700327 static final int HEAVY_WEIGHT_APP_MEM;
328 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800329 static final int VISIBLE_APP_MEM;
330 static final int FOREGROUND_APP_MEM;
331
332 // The minimum number of hidden apps we want to be able to keep around,
333 // without empty apps being able to push them out of memory.
334 static final int MIN_HIDDEN_APPS = 2;
335
Dianne Hackborn8633e682010-04-22 16:03:41 -0700336 // The maximum number of hidden processes we will keep around before
337 // killing them; this is just a control to not let us go too crazy with
338 // keeping around processes on devices with large amounts of RAM.
339 static final int MAX_HIDDEN_APPS = 15;
340
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800341 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700342 // been idle for less than 15 seconds.
343 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800344
345 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700346 // been idle for less than 120 seconds.
347 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800348
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700349 static int getIntProp(String name, boolean allowZero) {
350 String str = SystemProperties.get(name);
351 if (str == null) {
352 throw new IllegalArgumentException("Property not defined: " + name);
353 }
354 int val = Integer.valueOf(str);
355 if (val == 0 && !allowZero) {
356 throw new IllegalArgumentException("Property must not be zero: " + name);
357 }
358 return val;
359 }
360
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800361 static {
362 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700363 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
364 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
365 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
366 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
367 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
368 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
369 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
370 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
371 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
372 // These days we use the last empty slot for hidden apps as well.
373 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
374 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
375 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
376 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
377 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
378 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
379 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
380 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
381 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
382 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384
Dan Egnor42471dd2010-01-07 17:25:22 -0800385 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386
387 static final String[] EMPTY_STRING_ARRAY = new String[0];
388
389 enum ActivityState {
390 INITIALIZING,
391 RESUMED,
392 PAUSING,
393 PAUSED,
394 STOPPING,
395 STOPPED,
396 FINISHING,
397 DESTROYING,
398 DESTROYED
399 }
400
401 /**
402 * The back history of all previous (and possibly still
403 * running) activities. It contains HistoryRecord objects.
404 */
405 final ArrayList mHistory = new ArrayList();
406
407 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700408 * Description of a request to start a new activity, which has been held
409 * due to app switches being disabled.
410 */
411 class PendingActivityLaunch {
412 HistoryRecord r;
413 HistoryRecord sourceRecord;
414 Uri[] grantedUriPermissions;
415 int grantedMode;
416 boolean onlyIfNeeded;
417 }
418
419 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
420 = new ArrayList<PendingActivityLaunch>();
421
422 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800423 * List of people waiting to find out about the next launched activity.
424 */
425 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
426 = new ArrayList<IActivityManager.WaitResult>();
427
428 /**
429 * List of people waiting to find out about the next visible activity.
430 */
431 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
432 = new ArrayList<IActivityManager.WaitResult>();
433
434 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 * List of all active broadcasts that are to be executed immediately
436 * (without waiting for another broadcast to finish). Currently this only
437 * contains broadcasts to registered receivers, to avoid spinning up
438 * a bunch of processes to execute IntentReceiver components.
439 */
440 final ArrayList<BroadcastRecord> mParallelBroadcasts
441 = new ArrayList<BroadcastRecord>();
442
443 /**
444 * List of all active broadcasts that are to be executed one at a time.
445 * The object at the top of the list is the currently activity broadcasts;
446 * those after it are waiting for the top to finish..
447 */
448 final ArrayList<BroadcastRecord> mOrderedBroadcasts
449 = new ArrayList<BroadcastRecord>();
450
451 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800452 * Historical data of past broadcasts, for debugging.
453 */
454 static final int MAX_BROADCAST_HISTORY = 100;
455 final BroadcastRecord[] mBroadcastHistory
456 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
457
458 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 * Set when we current have a BROADCAST_INTENT_MSG in flight.
460 */
461 boolean mBroadcastsScheduled = false;
462
463 /**
464 * Set to indicate whether to issue an onUserLeaving callback when a
465 * newly launched activity is being brought in front of us.
466 */
467 boolean mUserLeaving = false;
468
469 /**
470 * When we are in the process of pausing an activity, before starting the
471 * next one, this variable holds the activity that is currently being paused.
472 */
473 HistoryRecord mPausingActivity = null;
474
475 /**
476 * Current activity that is resumed, or null if there is none.
477 */
478 HistoryRecord mResumedActivity = null;
479
480 /**
481 * Activity we have told the window manager to have key focus.
482 */
483 HistoryRecord mFocusedActivity = null;
484
485 /**
486 * This is the last activity that we put into the paused state. This is
487 * used to determine if we need to do an activity transition while sleeping,
488 * when we normally hold the top activity paused.
489 */
490 HistoryRecord mLastPausedActivity = null;
491
492 /**
493 * List of activities that are waiting for a new activity
494 * to become visible before completing whatever operation they are
495 * supposed to do.
496 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700497 final ArrayList<HistoryRecord> mWaitingVisibleActivities
498 = new ArrayList<HistoryRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499
500 /**
501 * List of activities that are ready to be stopped, but waiting
502 * for the next activity to settle down before doing so. It contains
503 * HistoryRecord objects.
504 */
505 final ArrayList<HistoryRecord> mStoppingActivities
506 = new ArrayList<HistoryRecord>();
507
508 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700509 * Animations that for the current transition have requested not to
510 * be considered for the transition animation.
511 */
512 final ArrayList<HistoryRecord> mNoAnimActivities
513 = new ArrayList<HistoryRecord>();
514
515 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516 * List of intents that were used to start the most recent tasks.
517 */
518 final ArrayList<TaskRecord> mRecentTasks
519 = new ArrayList<TaskRecord>();
520
521 /**
522 * List of activities that are ready to be finished, but waiting
523 * for the previous activity to settle down before doing so. It contains
524 * HistoryRecord objects.
525 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700526 final ArrayList<HistoryRecord> mFinishingActivities
527 = new ArrayList<HistoryRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528
529 /**
530 * All of the applications we currently have running organized by name.
531 * The keys are strings of the application package name (as
532 * returned by the package manager), and the keys are ApplicationRecord
533 * objects.
534 */
535 final ProcessMap<ProcessRecord> mProcessNames
536 = new ProcessMap<ProcessRecord>();
537
538 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700539 * The currently running heavy-weight process, if any.
540 */
541 ProcessRecord mHeavyWeightProcess = null;
542
543 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544 * The last time that various processes have crashed.
545 */
546 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
547
548 /**
549 * Set of applications that we consider to be bad, and will reject
550 * incoming broadcasts from (which the user has no control over).
551 * Processes are added to this set when they have crashed twice within
552 * a minimum amount of time; they are removed from it when they are
553 * later restarted (hopefully due to some user action). The value is the
554 * time it was added to the list.
555 */
556 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
557
558 /**
559 * All of the processes we currently have running organized by pid.
560 * The keys are the pid running the application.
561 *
562 * <p>NOTE: This object is protected by its own lock, NOT the global
563 * activity manager lock!
564 */
565 final SparseArray<ProcessRecord> mPidsSelfLocked
566 = new SparseArray<ProcessRecord>();
567
568 /**
569 * All of the processes that have been forced to be foreground. The key
570 * is the pid of the caller who requested it (we hold a death
571 * link on it).
572 */
573 abstract class ForegroundToken implements IBinder.DeathRecipient {
574 int pid;
575 IBinder token;
576 }
577 final SparseArray<ForegroundToken> mForegroundProcesses
578 = new SparseArray<ForegroundToken>();
579
580 /**
581 * List of records for processes that someone had tried to start before the
582 * system was ready. We don't start them at that point, but ensure they
583 * are started by the time booting is complete.
584 */
585 final ArrayList<ProcessRecord> mProcessesOnHold
586 = new ArrayList<ProcessRecord>();
587
588 /**
589 * List of records for processes that we have started and are waiting
590 * for them to call back. This is really only needed when running in
591 * single processes mode, in which case we do not have a unique pid for
592 * each process.
593 */
594 final ArrayList<ProcessRecord> mStartingProcesses
595 = new ArrayList<ProcessRecord>();
596
597 /**
598 * List of persistent applications that are in the process
599 * of being started.
600 */
601 final ArrayList<ProcessRecord> mPersistentStartingProcesses
602 = new ArrayList<ProcessRecord>();
603
604 /**
605 * Processes that are being forcibly torn down.
606 */
607 final ArrayList<ProcessRecord> mRemovedProcesses
608 = new ArrayList<ProcessRecord>();
609
610 /**
611 * List of running applications, sorted by recent usage.
612 * The first entry in the list is the least recently used.
613 * It contains ApplicationRecord objects. This list does NOT include
614 * any persistent application records (since we never want to exit them).
615 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800616 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617 = new ArrayList<ProcessRecord>();
618
619 /**
620 * List of processes that should gc as soon as things are idle.
621 */
622 final ArrayList<ProcessRecord> mProcessesToGc
623 = new ArrayList<ProcessRecord>();
624
625 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800626 * This is the process holding what we currently consider to be
627 * the "home" activity.
628 */
629 private ProcessRecord mHomeProcess;
630
631 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 * List of running activities, sorted by recent usage.
633 * The first entry in the list is the least recently used.
634 * It contains HistoryRecord objects.
635 */
636 private final ArrayList mLRUActivities = new ArrayList();
637
638 /**
639 * Set of PendingResultRecord objects that are currently active.
640 */
641 final HashSet mPendingResultRecords = new HashSet();
642
643 /**
644 * Set of IntentSenderRecord objects that are currently active.
645 */
646 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
647 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
648
649 /**
650 * Intent broadcast that we have tried to start, but are
651 * waiting for its application's process to be created. We only
652 * need one (instead of a list) because we always process broadcasts
653 * one at a time, so no others can be started while waiting for this
654 * one.
655 */
656 BroadcastRecord mPendingBroadcast = null;
657
658 /**
659 * Keeps track of all IIntentReceivers that have been registered for
660 * broadcasts. Hash keys are the receiver IBinder, hash value is
661 * a ReceiverList.
662 */
663 final HashMap mRegisteredReceivers = new HashMap();
664
665 /**
666 * Resolver for broadcast intents to registered receivers.
667 * Holds BroadcastFilter (subclass of IntentFilter).
668 */
669 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
670 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
671 @Override
672 protected boolean allowFilterResult(
673 BroadcastFilter filter, List<BroadcastFilter> dest) {
674 IBinder target = filter.receiverList.receiver.asBinder();
675 for (int i=dest.size()-1; i>=0; i--) {
676 if (dest.get(i).receiverList.receiver.asBinder() == target) {
677 return false;
678 }
679 }
680 return true;
681 }
682 };
683
684 /**
685 * State of all active sticky broadcasts. Keys are the action of the
686 * sticky Intent, values are an ArrayList of all broadcasted intents with
687 * that action (which should usually be one).
688 */
689 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
690 new HashMap<String, ArrayList<Intent>>();
691
692 /**
693 * All currently running services.
694 */
695 final HashMap<ComponentName, ServiceRecord> mServices =
696 new HashMap<ComponentName, ServiceRecord>();
697
698 /**
699 * All currently running services indexed by the Intent used to start them.
700 */
701 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
702 new HashMap<Intent.FilterComparison, ServiceRecord>();
703
704 /**
705 * All currently bound service connections. Keys are the IBinder of
706 * the client's IServiceConnection.
707 */
708 final HashMap<IBinder, ConnectionRecord> mServiceConnections
709 = new HashMap<IBinder, ConnectionRecord>();
710
711 /**
712 * List of services that we have been asked to start,
713 * but haven't yet been able to. It is used to hold start requests
714 * while waiting for their corresponding application thread to get
715 * going.
716 */
717 final ArrayList<ServiceRecord> mPendingServices
718 = new ArrayList<ServiceRecord>();
719
720 /**
721 * List of services that are scheduled to restart following a crash.
722 */
723 final ArrayList<ServiceRecord> mRestartingServices
724 = new ArrayList<ServiceRecord>();
725
726 /**
727 * List of services that are in the process of being stopped.
728 */
729 final ArrayList<ServiceRecord> mStoppingServices
730 = new ArrayList<ServiceRecord>();
731
732 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700733 * Backup/restore process management
734 */
735 String mBackupAppName = null;
736 BackupRecord mBackupTarget = null;
737
738 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 * List of PendingThumbnailsRecord objects of clients who are still
740 * waiting to receive all of the thumbnails for a task.
741 */
742 final ArrayList mPendingThumbnails = new ArrayList();
743
744 /**
745 * List of HistoryRecord objects that have been finished and must
746 * still report back to a pending thumbnail receiver.
747 */
748 final ArrayList mCancelledThumbnails = new ArrayList();
749
750 /**
751 * All of the currently running global content providers. Keys are a
752 * string containing the provider name and values are a
753 * ContentProviderRecord object containing the data about it. Note
754 * that a single provider may be published under multiple names, so
755 * there may be multiple entries here for a single one in mProvidersByClass.
756 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700757 final HashMap<String, ContentProviderRecord> mProvidersByName
758 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759
760 /**
761 * All of the currently running global content providers. Keys are a
762 * string containing the provider's implementation class and values are a
763 * ContentProviderRecord object containing the data about it.
764 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700765 final HashMap<String, ContentProviderRecord> mProvidersByClass
766 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767
768 /**
769 * List of content providers who have clients waiting for them. The
770 * application is currently being launched and the provider will be
771 * removed from this list once it is published.
772 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700773 final ArrayList<ContentProviderRecord> mLaunchingProviders
774 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775
776 /**
777 * Global set of specific Uri permissions that have been granted.
778 */
779 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
780 = new SparseArray<HashMap<Uri, UriPermission>>();
781
782 /**
783 * Thread-local storage used to carry caller permissions over through
784 * indirect content-provider access.
785 * @see #ActivityManagerService.openContentUri()
786 */
787 private class Identity {
788 public int pid;
789 public int uid;
790
791 Identity(int _pid, int _uid) {
792 pid = _pid;
793 uid = _uid;
794 }
795 }
796 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
797
798 /**
799 * All information we have collected about the runtime performance of
800 * any user id that can impact battery performance.
801 */
802 final BatteryStatsService mBatteryStatsService;
803
804 /**
805 * information about component usage
806 */
807 final UsageStatsService mUsageStatsService;
808
809 /**
810 * Current configuration information. HistoryRecord objects are given
811 * a reference to this object to indicate which configuration they are
812 * currently running in, so this object must be kept immutable.
813 */
814 Configuration mConfiguration = new Configuration();
815
816 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800817 * Current sequencing integer of the configuration, for skipping old
818 * configurations.
819 */
820 int mConfigurationSeq = 0;
821
822 /**
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700823 * Set when we know we are going to be calling updateConfiguration()
824 * soon, so want to skip intermediate config checks.
825 */
826 boolean mConfigWillChange;
827
828 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700829 * Hardware-reported OpenGLES version.
830 */
831 final int GL_ES_VERSION;
832
833 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 * List of initialization arguments to pass to all processes when binding applications to them.
835 * For example, references to the commonly used services.
836 */
837 HashMap<String, IBinder> mAppBindArgs;
838
839 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700840 * Temporary to avoid allocations. Protected by main lock.
841 */
842 final StringBuilder mStringBuilder = new StringBuilder(256);
843
844 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 * Used to control how we initialize the service.
846 */
847 boolean mStartRunning = false;
848 ComponentName mTopComponent;
849 String mTopAction;
850 String mTopData;
851 boolean mSystemReady = false;
852 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700853 boolean mWaitingUpdate = false;
854 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855
856 Context mContext;
857
858 int mFactoryTest;
859
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700860 boolean mCheckedForSetup;
861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700863 * The time at which we will allow normal application switches again,
864 * after a call to {@link #stopAppSwitches()}.
865 */
866 long mAppSwitchesAllowedTime;
867
868 /**
869 * This is set to true after the first switch after mAppSwitchesAllowedTime
870 * is set; any switches after that will clear the time.
871 */
872 boolean mDidAppSwitch;
873
874 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 * Set while we are wanting to sleep, to prevent any
876 * activities from being started/resumed.
877 */
878 boolean mSleeping = false;
879
880 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700881 * Set if we are shutting down the system, similar to sleeping.
882 */
883 boolean mShuttingDown = false;
884
885 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 * Set when the system is going to sleep, until we have
887 * successfully paused the current activity and released our wake lock.
888 * At that point the system is allowed to actually sleep.
889 */
890 PowerManager.WakeLock mGoingToSleep;
891
892 /**
893 * We don't want to allow the device to go to sleep while in the process
894 * of launching an activity. This is primarily to allow alarm intent
895 * receivers to launch an activity and get that to run before the device
896 * goes back to sleep.
897 */
898 PowerManager.WakeLock mLaunchingActivity;
899
900 /**
901 * Task identifier that activities are currently being started
902 * in. Incremented each time a new task is created.
903 * todo: Replace this with a TokenSpace class that generates non-repeating
904 * integers that won't wrap.
905 */
906 int mCurTask = 1;
907
908 /**
909 * Current sequence id for oom_adj computation traversal.
910 */
911 int mAdjSeq = 0;
912
913 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700914 * Current sequence id for process LRU updating.
915 */
916 int mLruSeq = 0;
917
918 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
920 * is set, indicating the user wants processes started in such a way
921 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
922 * running in each process (thus no pre-initialized process, etc).
923 */
924 boolean mSimpleProcessManagement = false;
925
926 /**
927 * System monitoring: number of processes that died since the last
928 * N procs were started.
929 */
930 int[] mProcDeaths = new int[20];
931
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700932 /**
933 * This is set if we had to do a delayed dexopt of an app before launching
934 * it, to increasing the ANR timeouts in that case.
935 */
936 boolean mDidDexOpt;
937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 String mDebugApp = null;
939 boolean mWaitForDebugger = false;
940 boolean mDebugTransient = false;
941 String mOrigDebugApp = null;
942 boolean mOrigWaitForDebugger = false;
943 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700944 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700946 final RemoteCallbackList<IActivityWatcher> mWatchers
947 = new RemoteCallbackList<IActivityWatcher>();
948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 /**
950 * Callback of last caller to {@link #requestPss}.
951 */
952 Runnable mRequestPssCallback;
953
954 /**
955 * Remaining processes for which we are waiting results from the last
956 * call to {@link #requestPss}.
957 */
958 final ArrayList<ProcessRecord> mRequestPssList
959 = new ArrayList<ProcessRecord>();
960
961 /**
962 * Runtime statistics collection thread. This object's lock is used to
963 * protect all related state.
964 */
965 final Thread mProcessStatsThread;
966
967 /**
968 * Used to collect process stats when showing not responding dialog.
969 * Protected by mProcessStatsThread.
970 */
971 final ProcessStats mProcessStats = new ProcessStats(
972 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700973 final AtomicLong mLastCpuTime = new AtomicLong(0);
974 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 long mLastWriteTime = 0;
977
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700978 long mInitialStartTime = 0;
979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 /**
981 * Set to true after the system has finished booting.
982 */
983 boolean mBooted = false;
984
985 int mProcessLimit = 0;
986
987 WindowManagerService mWindowManager;
988
989 static ActivityManagerService mSelf;
990 static ActivityThread mSystemThread;
991
992 private final class AppDeathRecipient implements IBinder.DeathRecipient {
993 final ProcessRecord mApp;
994 final int mPid;
995 final IApplicationThread mAppThread;
996
997 AppDeathRecipient(ProcessRecord app, int pid,
998 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800999 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 TAG, "New death recipient " + this
1001 + " for thread " + thread.asBinder());
1002 mApp = app;
1003 mPid = pid;
1004 mAppThread = thread;
1005 }
1006
1007 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001008 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 TAG, "Death received in " + this
1010 + " for thread " + mAppThread.asBinder());
1011 removeRequestedPss(mApp);
1012 synchronized(ActivityManagerService.this) {
1013 appDiedLocked(mApp, mPid, mAppThread);
1014 }
1015 }
1016 }
1017
1018 static final int SHOW_ERROR_MSG = 1;
1019 static final int SHOW_NOT_RESPONDING_MSG = 2;
1020 static final int SHOW_FACTORY_ERROR_MSG = 3;
1021 static final int UPDATE_CONFIGURATION_MSG = 4;
1022 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
1023 static final int WAIT_FOR_DEBUGGER_MSG = 6;
1024 static final int BROADCAST_INTENT_MSG = 7;
1025 static final int BROADCAST_TIMEOUT_MSG = 8;
1026 static final int PAUSE_TIMEOUT_MSG = 9;
1027 static final int IDLE_TIMEOUT_MSG = 10;
1028 static final int IDLE_NOW_MSG = 11;
1029 static final int SERVICE_TIMEOUT_MSG = 12;
1030 static final int UPDATE_TIME_ZONE = 13;
1031 static final int SHOW_UID_ERROR_MSG = 14;
1032 static final int IM_FEELING_LUCKY_MSG = 15;
1033 static final int LAUNCH_TIMEOUT_MSG = 16;
1034 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 static final int RESUME_TOP_ACTIVITY_MSG = 19;
1036 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001037 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001038 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001039 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001040 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
1041 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001042 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043
1044 AlertDialog mUidAlert;
1045
1046 final Handler mHandler = new Handler() {
1047 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001048 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 //}
1050
1051 public void handleMessage(Message msg) {
1052 switch (msg.what) {
1053 case SHOW_ERROR_MSG: {
1054 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 synchronized (ActivityManagerService.this) {
1056 ProcessRecord proc = (ProcessRecord)data.get("app");
1057 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001058 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059 return;
1060 }
1061 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001062 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001063 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 d.show();
1065 proc.crashDialog = d;
1066 } else {
1067 // The device is asleep, so just pretend that the user
1068 // saw a crash dialog and hit "force quit".
1069 res.set(0);
1070 }
1071 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001072
1073 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 } break;
1075 case SHOW_NOT_RESPONDING_MSG: {
1076 synchronized (ActivityManagerService.this) {
1077 HashMap data = (HashMap) msg.obj;
1078 ProcessRecord proc = (ProcessRecord)data.get("app");
1079 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001080 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 return;
1082 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001083
1084 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1085 null, null, 0, null, null, null,
1086 false, false, MY_PID, Process.SYSTEM_UID);
1087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1089 mContext, proc, (HistoryRecord)data.get("activity"));
1090 d.show();
1091 proc.anrDialog = d;
1092 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001093
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001094 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001095 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001096 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1097 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1098 synchronized (ActivityManagerService.this) {
1099 ProcessRecord proc = (ProcessRecord) data.get("app");
1100 if (proc == null) {
1101 Slog.e(TAG, "App not found when showing strict mode dialog.");
1102 break;
1103 }
1104 if (proc.crashDialog != null) {
1105 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1106 return;
1107 }
1108 AppErrorResult res = (AppErrorResult) data.get("result");
1109 if (!mSleeping && !mShuttingDown) {
1110 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1111 d.show();
1112 proc.crashDialog = d;
1113 } else {
1114 // The device is asleep, so just pretend that the user
1115 // saw a crash dialog and hit "force quit".
1116 res.set(0);
1117 }
1118 }
1119 ensureBootCompleted();
1120 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 case SHOW_FACTORY_ERROR_MSG: {
1122 Dialog d = new FactoryErrorDialog(
1123 mContext, msg.getData().getCharSequence("msg"));
1124 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001125 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001126 } break;
1127 case UPDATE_CONFIGURATION_MSG: {
1128 final ContentResolver resolver = mContext.getContentResolver();
1129 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1130 } break;
1131 case GC_BACKGROUND_PROCESSES_MSG: {
1132 synchronized (ActivityManagerService.this) {
1133 performAppGcsIfAppropriateLocked();
1134 }
1135 } break;
1136 case WAIT_FOR_DEBUGGER_MSG: {
1137 synchronized (ActivityManagerService.this) {
1138 ProcessRecord app = (ProcessRecord)msg.obj;
1139 if (msg.arg1 != 0) {
1140 if (!app.waitedForDebugger) {
1141 Dialog d = new AppWaitingForDebuggerDialog(
1142 ActivityManagerService.this,
1143 mContext, app);
1144 app.waitDialog = d;
1145 app.waitedForDebugger = true;
1146 d.show();
1147 }
1148 } else {
1149 if (app.waitDialog != null) {
1150 app.waitDialog.dismiss();
1151 app.waitDialog = null;
1152 }
1153 }
1154 }
1155 } break;
1156 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001157 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 TAG, "Received BROADCAST_INTENT_MSG");
1159 processNextBroadcast(true);
1160 } break;
1161 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001162 if (mDidDexOpt) {
1163 mDidDexOpt = false;
1164 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1165 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1166 return;
1167 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001168 // Only process broadcast timeouts if the system is ready. That way
1169 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1170 // to do heavy lifting for system up
1171 if (mSystemReady) {
1172 broadcastTimeout();
1173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 } break;
1175 case PAUSE_TIMEOUT_MSG: {
1176 IBinder token = (IBinder)msg.obj;
1177 // We don't at this point know if the activity is fullscreen,
1178 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001179 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 activityPaused(token, null, true);
1181 } break;
1182 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001183 if (mDidDexOpt) {
1184 mDidDexOpt = false;
1185 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1186 nmsg.obj = msg.obj;
1187 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1188 return;
1189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 // We don't at this point know if the activity is fullscreen,
1191 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001192 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001193 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001194 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195 } break;
1196 case DESTROY_TIMEOUT_MSG: {
1197 IBinder token = (IBinder)msg.obj;
1198 // We don't at this point know if the activity is fullscreen,
1199 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001200 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 activityDestroyed(token);
1202 } break;
1203 case IDLE_NOW_MSG: {
1204 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001205 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 } break;
1207 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001208 if (mDidDexOpt) {
1209 mDidDexOpt = false;
1210 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1211 nmsg.obj = msg.obj;
1212 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1213 return;
1214 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 serviceTimeout((ProcessRecord)msg.obj);
1216 } break;
1217 case UPDATE_TIME_ZONE: {
1218 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001219 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1220 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 if (r.thread != null) {
1222 try {
1223 r.thread.updateTimeZone();
1224 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001225 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 }
1227 }
1228 }
1229 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001230 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 case SHOW_UID_ERROR_MSG: {
1232 // XXX This is a temporary dialog, no need to localize.
1233 AlertDialog d = new BaseErrorDialog(mContext);
1234 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1235 d.setCancelable(false);
1236 d.setTitle("System UIDs Inconsistent");
1237 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1238 d.setButton("I'm Feeling Lucky",
1239 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1240 mUidAlert = d;
1241 d.show();
1242 } break;
1243 case IM_FEELING_LUCKY_MSG: {
1244 if (mUidAlert != null) {
1245 mUidAlert.dismiss();
1246 mUidAlert = null;
1247 }
1248 } break;
1249 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001250 if (mDidDexOpt) {
1251 mDidDexOpt = false;
1252 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1253 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1254 return;
1255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 synchronized (ActivityManagerService.this) {
1257 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001258 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 mLaunchingActivity.release();
1260 }
1261 }
1262 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001263 case RESUME_TOP_ACTIVITY_MSG: {
1264 synchronized (ActivityManagerService.this) {
1265 resumeTopActivityLocked(null);
1266 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001267 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001268 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001269 if (mDidDexOpt) {
1270 mDidDexOpt = false;
1271 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1272 nmsg.obj = msg.obj;
1273 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1274 return;
1275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001276 ProcessRecord app = (ProcessRecord)msg.obj;
1277 synchronized (ActivityManagerService.this) {
1278 processStartTimedOutLocked(app);
1279 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001280 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001281 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1282 synchronized (ActivityManagerService.this) {
1283 doPendingActivityLaunchesLocked(true);
1284 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001285 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001286 case KILL_APPLICATION_MSG: {
1287 synchronized (ActivityManagerService.this) {
1288 int uid = msg.arg1;
1289 boolean restart = (msg.arg2 == 1);
1290 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001291 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001292 }
1293 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001294 case FINALIZE_PENDING_INTENT_MSG: {
1295 ((PendingIntentRecord)msg.obj).completeFinalize();
1296 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001297 case POST_HEAVY_NOTIFICATION_MSG: {
1298 INotificationManager inm = NotificationManager.getService();
1299 if (inm == null) {
1300 return;
1301 }
1302
1303 HistoryRecord root = (HistoryRecord)msg.obj;
1304 ProcessRecord process = root.app;
1305 if (process == null) {
1306 return;
1307 }
1308
1309 try {
1310 Context context = mContext.createPackageContext(process.info.packageName, 0);
1311 String text = mContext.getString(R.string.heavy_weight_notification,
1312 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1313 Notification notification = new Notification();
1314 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1315 notification.when = 0;
1316 notification.flags = Notification.FLAG_ONGOING_EVENT;
1317 notification.tickerText = text;
1318 notification.defaults = 0; // please be quiet
1319 notification.sound = null;
1320 notification.vibrate = null;
1321 notification.setLatestEventInfo(context, text,
1322 mContext.getText(R.string.heavy_weight_notification_detail),
1323 PendingIntent.getActivity(mContext, 0, root.intent,
1324 PendingIntent.FLAG_CANCEL_CURRENT));
1325
1326 try {
1327 int[] outId = new int[1];
1328 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1329 notification, outId);
1330 } catch (RuntimeException e) {
1331 Slog.w(ActivityManagerService.TAG,
1332 "Error showing notification for heavy-weight app", e);
1333 } catch (RemoteException e) {
1334 }
1335 } catch (NameNotFoundException e) {
1336 Log.w(TAG, "Unable to create context for heavy notification", e);
1337 }
1338 } break;
1339 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1340 INotificationManager inm = NotificationManager.getService();
1341 if (inm == null) {
1342 return;
1343 }
1344 try {
1345 inm.cancelNotification("android",
1346 R.string.heavy_weight_notification);
1347 } catch (RuntimeException e) {
1348 Slog.w(ActivityManagerService.TAG,
1349 "Error canceling notification for service", e);
1350 } catch (RemoteException e) {
1351 }
1352 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 }
1354 }
1355 };
1356
1357 public static void setSystemProcess() {
1358 try {
1359 ActivityManagerService m = mSelf;
1360
1361 ServiceManager.addService("activity", m);
1362 ServiceManager.addService("meminfo", new MemBinder(m));
1363 if (MONITOR_CPU_USAGE) {
1364 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 ServiceManager.addService("permission", new PermissionController(m));
1367
1368 ApplicationInfo info =
1369 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001370 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001371 mSystemThread.installSystemApplicationInfo(info);
1372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 synchronized (mSelf) {
1374 ProcessRecord app = mSelf.newProcessRecordLocked(
1375 mSystemThread.getApplicationThread(), info,
1376 info.processName);
1377 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001378 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 app.maxAdj = SYSTEM_ADJ;
1380 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1381 synchronized (mSelf.mPidsSelfLocked) {
1382 mSelf.mPidsSelfLocked.put(app.pid, app);
1383 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001384 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 }
1386 } catch (PackageManager.NameNotFoundException e) {
1387 throw new RuntimeException(
1388 "Unable to find android system package", e);
1389 }
1390 }
1391
1392 public void setWindowManager(WindowManagerService wm) {
1393 mWindowManager = wm;
1394 }
1395
1396 public static final Context main(int factoryTest) {
1397 AThread thr = new AThread();
1398 thr.start();
1399
1400 synchronized (thr) {
1401 while (thr.mService == null) {
1402 try {
1403 thr.wait();
1404 } catch (InterruptedException e) {
1405 }
1406 }
1407 }
1408
1409 ActivityManagerService m = thr.mService;
1410 mSelf = m;
1411 ActivityThread at = ActivityThread.systemMain();
1412 mSystemThread = at;
1413 Context context = at.getSystemContext();
1414 m.mContext = context;
1415 m.mFactoryTest = factoryTest;
1416 PowerManager pm =
1417 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1418 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1419 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1420 m.mLaunchingActivity.setReferenceCounted(false);
1421
1422 m.mBatteryStatsService.publish(context);
1423 m.mUsageStatsService.publish(context);
1424
1425 synchronized (thr) {
1426 thr.mReady = true;
1427 thr.notifyAll();
1428 }
1429
1430 m.startRunning(null, null, null, null);
1431
1432 return context;
1433 }
1434
1435 public static ActivityManagerService self() {
1436 return mSelf;
1437 }
1438
1439 static class AThread extends Thread {
1440 ActivityManagerService mService;
1441 boolean mReady = false;
1442
1443 public AThread() {
1444 super("ActivityManager");
1445 }
1446
1447 public void run() {
1448 Looper.prepare();
1449
1450 android.os.Process.setThreadPriority(
1451 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1452
1453 ActivityManagerService m = new ActivityManagerService();
1454
1455 synchronized (this) {
1456 mService = m;
1457 notifyAll();
1458 }
1459
1460 synchronized (this) {
1461 while (!mReady) {
1462 try {
1463 wait();
1464 } catch (InterruptedException e) {
1465 }
1466 }
1467 }
1468
1469 Looper.loop();
1470 }
1471 }
1472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 static class MemBinder extends Binder {
1474 ActivityManagerService mActivityManagerService;
1475 MemBinder(ActivityManagerService activityManagerService) {
1476 mActivityManagerService = activityManagerService;
1477 }
1478
1479 @Override
1480 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1481 ActivityManagerService service = mActivityManagerService;
1482 ArrayList<ProcessRecord> procs;
1483 synchronized (mActivityManagerService) {
1484 if (args != null && args.length > 0
1485 && args[0].charAt(0) != '-') {
1486 procs = new ArrayList<ProcessRecord>();
1487 int pid = -1;
1488 try {
1489 pid = Integer.parseInt(args[0]);
1490 } catch (NumberFormatException e) {
1491
1492 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001493 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1494 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 if (proc.pid == pid) {
1496 procs.add(proc);
1497 } else if (proc.processName.equals(args[0])) {
1498 procs.add(proc);
1499 }
1500 }
1501 if (procs.size() <= 0) {
1502 pw.println("No process found for: " + args[0]);
1503 return;
1504 }
1505 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001506 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 }
1508 }
1509 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1510 }
1511 }
1512
1513 static class CpuBinder extends Binder {
1514 ActivityManagerService mActivityManagerService;
1515 CpuBinder(ActivityManagerService activityManagerService) {
1516 mActivityManagerService = activityManagerService;
1517 }
1518
1519 @Override
1520 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1521 synchronized (mActivityManagerService.mProcessStatsThread) {
1522 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1523 }
1524 }
1525 }
1526
1527 private ActivityManagerService() {
1528 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1529 if (v != null && Integer.getInteger(v) != 0) {
1530 mSimpleProcessManagement = true;
1531 }
1532 v = System.getenv("ANDROID_DEBUG_APP");
1533 if (v != null) {
1534 mSimpleProcessManagement = true;
1535 }
1536
Joe Onorato8a9b2202010-02-26 18:56:32 -08001537 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 File dataDir = Environment.getDataDirectory();
1540 File systemDir = new File(dataDir, "system");
1541 systemDir.mkdirs();
1542 mBatteryStatsService = new BatteryStatsService(new File(
1543 systemDir, "batterystats.bin").toString());
1544 mBatteryStatsService.getActiveStatistics().readLocked();
1545 mBatteryStatsService.getActiveStatistics().writeLocked();
1546
1547 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001548 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549
Jack Palevichb90d28c2009-07-22 15:35:24 -07001550 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1551 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1552
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001553 mConfiguration.setToDefaults();
1554 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 mProcessStats.init();
1556
1557 // Add ourself to the Watchdog monitors.
1558 Watchdog.getInstance().addMonitor(this);
1559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 mProcessStatsThread = new Thread("ProcessStats") {
1561 public void run() {
1562 while (true) {
1563 try {
1564 try {
1565 synchronized(this) {
1566 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001567 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001569 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 // + ", write delay=" + nextWriteDelay);
1571 if (nextWriteDelay < nextCpuDelay) {
1572 nextCpuDelay = nextWriteDelay;
1573 }
1574 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001575 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 this.wait(nextCpuDelay);
1577 }
1578 }
1579 } catch (InterruptedException e) {
1580 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 updateCpuStatsNow();
1582 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001583 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 }
1585 }
1586 }
1587 };
1588 mProcessStatsThread.start();
1589 }
1590
1591 @Override
1592 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1593 throws RemoteException {
1594 try {
1595 return super.onTransact(code, data, reply, flags);
1596 } catch (RuntimeException e) {
1597 // The activity manager only throws security exceptions, so let's
1598 // log all others.
1599 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001600 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 }
1602 throw e;
1603 }
1604 }
1605
1606 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001607 final long now = SystemClock.uptimeMillis();
1608 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1609 return;
1610 }
1611 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1612 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 mProcessStatsThread.notify();
1614 }
1615 }
1616 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 void updateCpuStatsNow() {
1619 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001620 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 final long now = SystemClock.uptimeMillis();
1622 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001625 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1626 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627 haveNewCpuStats = true;
1628 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001629 //Slog.i(TAG, mProcessStats.printCurrentState());
1630 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 // + mProcessStats.getTotalCpuPercent() + "%");
1632
Joe Onorato8a9b2202010-02-26 18:56:32 -08001633 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 if ("true".equals(SystemProperties.get("events.cpu"))) {
1635 int user = mProcessStats.getLastUserTime();
1636 int system = mProcessStats.getLastSystemTime();
1637 int iowait = mProcessStats.getLastIoWaitTime();
1638 int irq = mProcessStats.getLastIrqTime();
1639 int softIrq = mProcessStats.getLastSoftIrqTime();
1640 int idle = mProcessStats.getLastIdleTime();
1641
1642 int total = user + system + iowait + irq + softIrq + idle;
1643 if (total == 0) total = 1;
1644
Doug Zongker2bec3d42009-12-04 12:52:44 -08001645 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 ((user+system+iowait+irq+softIrq) * 100) / total,
1647 (user * 100) / total,
1648 (system * 100) / total,
1649 (iowait * 100) / total,
1650 (irq * 100) / total,
1651 (softIrq * 100) / total);
1652 }
1653 }
1654
Amith Yamasanie43530a2009-08-21 13:11:37 -07001655 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001656 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001657 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 synchronized(mPidsSelfLocked) {
1659 if (haveNewCpuStats) {
1660 if (mBatteryStatsService.isOnBattery()) {
1661 final int N = mProcessStats.countWorkingStats();
1662 for (int i=0; i<N; i++) {
1663 ProcessStats.Stats st
1664 = mProcessStats.getWorkingStats(i);
1665 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1666 if (pr != null) {
1667 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1668 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001669 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001670 } else {
1671 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001672 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001673 if (ps != null) {
1674 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001675 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001676 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 }
1678 }
1679 }
1680 }
1681 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1684 mLastWriteTime = now;
1685 mBatteryStatsService.getActiveStatistics().writeLocked();
1686 }
1687 }
1688 }
1689 }
1690
1691 /**
1692 * Initialize the application bind args. These are passed to each
1693 * process when the bindApplication() IPC is sent to the process. They're
1694 * lazily setup to make sure the services are running when they're asked for.
1695 */
1696 private HashMap<String, IBinder> getCommonServicesLocked() {
1697 if (mAppBindArgs == null) {
1698 mAppBindArgs = new HashMap<String, IBinder>();
1699
1700 // Setup the application init args
1701 mAppBindArgs.put("package", ServiceManager.getService("package"));
1702 mAppBindArgs.put("window", ServiceManager.getService("window"));
1703 mAppBindArgs.put(Context.ALARM_SERVICE,
1704 ServiceManager.getService(Context.ALARM_SERVICE));
1705 }
1706 return mAppBindArgs;
1707 }
1708
1709 private final void setFocusedActivityLocked(HistoryRecord r) {
1710 if (mFocusedActivity != r) {
1711 mFocusedActivity = r;
1712 mWindowManager.setFocusedApp(r, true);
1713 }
1714 }
1715
Dianne Hackborn906497c2010-05-10 15:57:38 -07001716 private final void updateLruProcessInternalLocked(ProcessRecord app,
1717 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001719 int lrui = mLruProcesses.indexOf(app);
1720 if (lrui >= 0) mLruProcesses.remove(lrui);
1721
1722 int i = mLruProcesses.size()-1;
1723 int skipTop = 0;
1724
Dianne Hackborn906497c2010-05-10 15:57:38 -07001725 app.lruSeq = mLruSeq;
1726
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001727 // compute the new weight for this process.
1728 if (updateActivityTime) {
1729 app.lastActivityTime = SystemClock.uptimeMillis();
1730 }
1731 if (app.activities.size() > 0) {
1732 // If this process has activities, we more strongly want to keep
1733 // it around.
1734 app.lruWeight = app.lastActivityTime;
1735 } else if (app.pubProviders.size() > 0) {
1736 // If this process contains content providers, we want to keep
1737 // it a little more strongly.
1738 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1739 // Also don't let it kick out the first few "real" hidden processes.
1740 skipTop = MIN_HIDDEN_APPS;
1741 } else {
1742 // If this process doesn't have activities, we less strongly
1743 // want to keep it around, and generally want to avoid getting
1744 // in front of any very recently used activities.
1745 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1746 // Also don't let it kick out the first few "real" hidden processes.
1747 skipTop = MIN_HIDDEN_APPS;
1748 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001749
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001750 while (i >= 0) {
1751 ProcessRecord p = mLruProcesses.get(i);
1752 // If this app shouldn't be in front of the first N background
1753 // apps, then skip over that many that are currently hidden.
1754 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1755 skipTop--;
1756 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001757 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001758 mLruProcesses.add(i+1, app);
1759 break;
1760 }
1761 i--;
1762 }
1763 if (i < 0) {
1764 mLruProcesses.add(0, app);
1765 }
1766
Dianne Hackborn906497c2010-05-10 15:57:38 -07001767 // If the app is currently using a content provider or service,
1768 // bump those processes as well.
1769 if (app.connections.size() > 0) {
1770 for (ConnectionRecord cr : app.connections) {
1771 if (cr.binding != null && cr.binding.service != null
1772 && cr.binding.service.app != null
1773 && cr.binding.service.app.lruSeq != mLruSeq) {
1774 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1775 updateActivityTime, i+1);
1776 }
1777 }
1778 }
1779 if (app.conProviders.size() > 0) {
1780 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1781 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1782 updateLruProcessInternalLocked(cpr.app, oomAdj,
1783 updateActivityTime, i+1);
1784 }
1785 }
1786 }
1787
Joe Onorato8a9b2202010-02-26 18:56:32 -08001788 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 if (oomAdj) {
1790 updateOomAdjLocked();
1791 }
1792 }
1793
Dianne Hackborn906497c2010-05-10 15:57:38 -07001794 private final void updateLruProcessLocked(ProcessRecord app,
1795 boolean oomAdj, boolean updateActivityTime) {
1796 mLruSeq++;
1797 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1798 }
1799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 private final boolean updateLRUListLocked(HistoryRecord r) {
1801 final boolean hadit = mLRUActivities.remove(r);
1802 mLRUActivities.add(r);
1803 return hadit;
1804 }
1805
1806 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1807 int i = mHistory.size()-1;
1808 while (i >= 0) {
1809 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1810 if (!r.finishing && r != notTop) {
1811 return r;
1812 }
1813 i--;
1814 }
1815 return null;
1816 }
1817
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001818 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1819 int i = mHistory.size()-1;
1820 while (i >= 0) {
1821 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1822 if (!r.finishing && !r.delayedResume && r != notTop) {
1823 return r;
1824 }
1825 i--;
1826 }
1827 return null;
1828 }
1829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 /**
1831 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001832 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001833 *
1834 * @param token If non-null, any history records matching this token will be skipped.
1835 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1836 *
1837 * @return Returns the HistoryRecord of the next activity on the stack.
1838 */
1839 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1840 int i = mHistory.size()-1;
1841 while (i >= 0) {
1842 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1843 // Note: the taskId check depends on real taskId fields being non-zero
1844 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1845 return r;
1846 }
1847 i--;
1848 }
1849 return null;
1850 }
1851
1852 private final ProcessRecord getProcessRecordLocked(
1853 String processName, int uid) {
1854 if (uid == Process.SYSTEM_UID) {
1855 // The system gets to run in any process. If there are multiple
1856 // processes with the same uid, just pick the first (this
1857 // should never happen).
1858 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1859 processName);
1860 return procs != null ? procs.valueAt(0) : null;
1861 }
1862 ProcessRecord proc = mProcessNames.get(processName, uid);
1863 return proc;
1864 }
1865
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001866 private void ensurePackageDexOpt(String packageName) {
1867 IPackageManager pm = ActivityThread.getPackageManager();
1868 try {
1869 if (pm.performDexOpt(packageName)) {
1870 mDidDexOpt = true;
1871 }
1872 } catch (RemoteException e) {
1873 }
1874 }
1875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 private boolean isNextTransitionForward() {
1877 int transit = mWindowManager.getPendingAppTransition();
1878 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1879 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1880 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1881 }
1882
1883 private final boolean realStartActivityLocked(HistoryRecord r,
1884 ProcessRecord app, boolean andResume, boolean checkConfig)
1885 throws RemoteException {
1886
1887 r.startFreezingScreenLocked(app, 0);
1888 mWindowManager.setAppVisibility(r, true);
1889
1890 // Have the window manager re-evaluate the orientation of
1891 // the screen based on the new activity order. Note that
1892 // as a result of this, it can call back into the activity
1893 // manager with a new orientation. We don't care about that,
1894 // because the activity is not currently running so we are
1895 // just restarting it anyway.
1896 if (checkConfig) {
1897 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001898 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899 r.mayFreezeScreenLocked(app) ? r : null);
1900 updateConfigurationLocked(config, r);
1901 }
1902
1903 r.app = app;
1904
Joe Onorato8a9b2202010-02-26 18:56:32 -08001905 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906
1907 int idx = app.activities.indexOf(r);
1908 if (idx < 0) {
1909 app.activities.add(r);
1910 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001911 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912
1913 try {
1914 if (app.thread == null) {
1915 throw new RemoteException();
1916 }
1917 List<ResultInfo> results = null;
1918 List<Intent> newIntents = null;
1919 if (andResume) {
1920 results = r.results;
1921 newIntents = r.newIntents;
1922 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001923 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 + " icicle=" + r.icicle
1925 + " with results=" + results + " newIntents=" + newIntents
1926 + " andResume=" + andResume);
1927 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001928 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 System.identityHashCode(r),
1930 r.task.taskId, r.shortComponentName);
1931 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001932 if (r.isHomeActivity) {
1933 mHomeProcess = app;
1934 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001935 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001936 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001937 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 r.info, r.icicle, results, newIntents, !andResume,
1939 isNextTransitionForward());
Dianne Hackborn860755f2010-06-03 18:47:52 -07001940
1941 if ((app.info.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
1942 // This may be a heavy-weight process! Note that the package
1943 // manager will ensure that only activity can run in the main
1944 // process of the .apk, which is the only thing that will be
1945 // considered heavy-weight.
1946 if (app.processName.equals(app.info.packageName)) {
1947 if (mHeavyWeightProcess != null && mHeavyWeightProcess != app) {
1948 Log.w(TAG, "Starting new heavy weight process " + app
1949 + " when already running " + mHeavyWeightProcess);
1950 }
1951 mHeavyWeightProcess = app;
1952 Message msg = mHandler.obtainMessage(POST_HEAVY_NOTIFICATION_MSG);
1953 msg.obj = r;
1954 mHandler.sendMessage(msg);
1955 }
1956 }
1957
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001958 } catch (RemoteException e) {
1959 if (r.launchFailed) {
1960 // This is the second time we failed -- finish activity
1961 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001962 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001963 + r.intent.getComponent().flattenToShortString()
1964 + ", giving up", e);
1965 appDiedLocked(app, app.pid, app.thread);
1966 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1967 "2nd-crash");
1968 return false;
1969 }
1970
1971 // This is the first time we failed -- restart process and
1972 // retry.
1973 app.activities.remove(r);
1974 throw e;
1975 }
1976
1977 r.launchFailed = false;
1978 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001979 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 + " being launched, but already in LRU list");
1981 }
1982
1983 if (andResume) {
1984 // As part of the process of launching, ActivityThread also performs
1985 // a resume.
1986 r.state = ActivityState.RESUMED;
1987 r.icicle = null;
1988 r.haveState = false;
1989 r.stopped = false;
1990 mResumedActivity = r;
1991 r.task.touchActiveTime();
1992 completeResumeLocked(r);
1993 pauseIfSleepingLocked();
1994 } else {
1995 // This activity is not starting in the resumed state... which
1996 // should look like we asked it to pause+stop (but remain visible),
1997 // and it has done so and reported back the current icicle and
1998 // other state.
1999 r.state = ActivityState.STOPPED;
2000 r.stopped = true;
2001 }
2002
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002003 // Launch the new version setup screen if needed. We do this -after-
2004 // launching the initial activity (that is, home), so that it can have
2005 // a chance to initialize itself while in the background, making the
2006 // switch back to it faster and look better.
2007 startSetupActivityLocked();
2008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002009 return true;
2010 }
2011
2012 private final void startSpecificActivityLocked(HistoryRecord r,
2013 boolean andResume, boolean checkConfig) {
2014 // Is this activity's application already running?
2015 ProcessRecord app = getProcessRecordLocked(r.processName,
2016 r.info.applicationInfo.uid);
2017
2018 if (r.startTime == 0) {
2019 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002020 if (mInitialStartTime == 0) {
2021 mInitialStartTime = r.startTime;
2022 }
2023 } else if (mInitialStartTime == 0) {
2024 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 }
2026
2027 if (app != null && app.thread != null) {
2028 try {
2029 realStartActivityLocked(r, app, andResume, checkConfig);
2030 return;
2031 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002032 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002033 + r.intent.getComponent().flattenToShortString(), e);
2034 }
2035
2036 // If a dead object exception was thrown -- fall through to
2037 // restart the application.
2038 }
2039
2040 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002041 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002042 }
2043
2044 private final ProcessRecord startProcessLocked(String processName,
2045 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002046 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
2048 // We don't have to do anything more if:
2049 // (1) There is an existing application record; and
2050 // (2) The caller doesn't think it is dead, OR there is no thread
2051 // object attached to it so we know it couldn't have crashed; and
2052 // (3) There is a pid assigned to it, so it is either starting or
2053 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002054 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 + " app=" + app + " knownToBeDead=" + knownToBeDead
2056 + " thread=" + (app != null ? app.thread : null)
2057 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01002058 if (app != null && app.pid > 0) {
2059 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002060 // We already have the app running, or are waiting for it to
2061 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01002062 return app;
2063 } else {
2064 // An application record is attached to a previous process,
2065 // clean it up now.
2066 handleAppDiedLocked(app, true);
2067 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002068 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 String hostingNameStr = hostingName != null
2071 ? hostingName.flattenToShortString() : null;
2072
2073 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
2074 // If we are in the background, then check to see if this process
2075 // is bad. If so, we will just silently fail.
2076 if (mBadProcesses.get(info.processName, info.uid) != null) {
2077 return null;
2078 }
2079 } else {
2080 // When the user is explicitly starting a process, then clear its
2081 // crash count so that we won't make it bad until they see at
2082 // least one crash dialog again, and make the process good again
2083 // if it had been bad.
2084 mProcessCrashTimes.remove(info.processName, info.uid);
2085 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002086 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002087 info.processName);
2088 mBadProcesses.remove(info.processName, info.uid);
2089 if (app != null) {
2090 app.bad = false;
2091 }
2092 }
2093 }
2094
2095 if (app == null) {
2096 app = newProcessRecordLocked(null, info, processName);
2097 mProcessNames.put(processName, info.uid, app);
2098 } else {
2099 // If this is a new package in the process, add the package to the list
2100 app.addPackage(info.packageName);
2101 }
2102
2103 // If the system is not ready yet, then hold off on starting this
2104 // process until it is.
2105 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002106 && !isAllowedWhileBooting(info)
2107 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002108 if (!mProcessesOnHold.contains(app)) {
2109 mProcessesOnHold.add(app);
2110 }
2111 return app;
2112 }
2113
2114 startProcessLocked(app, hostingType, hostingNameStr);
2115 return (app.pid != 0) ? app : null;
2116 }
2117
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002118 boolean isAllowedWhileBooting(ApplicationInfo ai) {
2119 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
2120 }
2121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122 private final void startProcessLocked(ProcessRecord app,
2123 String hostingType, String hostingNameStr) {
2124 if (app.pid > 0 && app.pid != MY_PID) {
2125 synchronized (mPidsSelfLocked) {
2126 mPidsSelfLocked.remove(app.pid);
2127 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
2128 }
2129 app.pid = 0;
2130 }
2131
2132 mProcessesOnHold.remove(app);
2133
2134 updateCpuStats();
2135
2136 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
2137 mProcDeaths[0] = 0;
2138
2139 try {
2140 int uid = app.info.uid;
2141 int[] gids = null;
2142 try {
2143 gids = mContext.getPackageManager().getPackageGids(
2144 app.info.packageName);
2145 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002146 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 }
2148 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
2149 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2150 && mTopComponent != null
2151 && app.processName.equals(mTopComponent.getPackageName())) {
2152 uid = 0;
2153 }
2154 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
2155 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
2156 uid = 0;
2157 }
2158 }
2159 int debugFlags = 0;
2160 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
2161 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
2162 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08002163 // Run the app in safe mode if its manifest requests so or the
2164 // system is booted in safe mode.
2165 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
2166 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08002167 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
2168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002169 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
2170 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
2171 }
2172 if ("1".equals(SystemProperties.get("debug.assert"))) {
2173 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2174 }
2175 int pid = Process.start("android.app.ActivityThread",
2176 mSimpleProcessManagement ? app.processName : null, uid, uid,
2177 gids, debugFlags, null);
2178 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2179 synchronized (bs) {
2180 if (bs.isOnBattery()) {
2181 app.batteryStats.incStartsLocked();
2182 }
2183 }
2184
Doug Zongker2bec3d42009-12-04 12:52:44 -08002185 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 app.processName, hostingType,
2187 hostingNameStr != null ? hostingNameStr : "");
2188
2189 if (app.persistent) {
2190 Watchdog.getInstance().processStarted(app, app.processName, pid);
2191 }
2192
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002193 StringBuilder buf = mStringBuilder;
2194 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195 buf.append("Start proc ");
2196 buf.append(app.processName);
2197 buf.append(" for ");
2198 buf.append(hostingType);
2199 if (hostingNameStr != null) {
2200 buf.append(" ");
2201 buf.append(hostingNameStr);
2202 }
2203 buf.append(": pid=");
2204 buf.append(pid);
2205 buf.append(" uid=");
2206 buf.append(uid);
2207 buf.append(" gids={");
2208 if (gids != null) {
2209 for (int gi=0; gi<gids.length; gi++) {
2210 if (gi != 0) buf.append(", ");
2211 buf.append(gids[gi]);
2212
2213 }
2214 }
2215 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002216 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002217 if (pid == 0 || pid == MY_PID) {
2218 // Processes are being emulated with threads.
2219 app.pid = MY_PID;
2220 app.removed = false;
2221 mStartingProcesses.add(app);
2222 } else if (pid > 0) {
2223 app.pid = pid;
2224 app.removed = false;
2225 synchronized (mPidsSelfLocked) {
2226 this.mPidsSelfLocked.put(pid, app);
2227 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2228 msg.obj = app;
2229 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2230 }
2231 } else {
2232 app.pid = 0;
2233 RuntimeException e = new RuntimeException(
2234 "Failure starting process " + app.processName
2235 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002236 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237 }
2238 } catch (RuntimeException e) {
2239 // XXX do better error recovery.
2240 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002241 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002242 }
2243 }
2244
2245 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2246 if (mPausingActivity != null) {
2247 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002248 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249 + mPausingActivity, e);
2250 }
2251 HistoryRecord prev = mResumedActivity;
2252 if (prev == null) {
2253 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002254 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002255 resumeTopActivityLocked(null);
2256 return;
2257 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002258 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 mResumedActivity = null;
2260 mPausingActivity = prev;
2261 mLastPausedActivity = prev;
2262 prev.state = ActivityState.PAUSING;
2263 prev.task.touchActiveTime();
2264
2265 updateCpuStats();
2266
2267 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002268 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002270 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 System.identityHashCode(prev),
2272 prev.shortComponentName);
2273 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2274 prev.configChangeFlags);
2275 updateUsageStats(prev, false);
2276 } catch (Exception e) {
2277 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002278 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 mPausingActivity = null;
2280 mLastPausedActivity = null;
2281 }
2282 } else {
2283 mPausingActivity = null;
2284 mLastPausedActivity = null;
2285 }
2286
2287 // If we are not going to sleep, we want to ensure the device is
2288 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002289 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290 mLaunchingActivity.acquire();
2291 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2292 // To be safe, don't allow the wake lock to be held for too long.
2293 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2294 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2295 }
2296 }
2297
2298
2299 if (mPausingActivity != null) {
2300 // Have the window manager pause its key dispatching until the new
2301 // activity has started. If we're pausing the activity just because
2302 // the screen is being turned off and the UI is sleeping, don't interrupt
2303 // key dispatch; the same activity will pick it up again on wakeup.
2304 if (!uiSleeping) {
2305 prev.pauseKeyDispatchingLocked();
2306 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002307 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002308 }
2309
2310 // Schedule a pause timeout in case the app doesn't respond.
2311 // We don't give it much time because this directly impacts the
2312 // responsiveness seen by the user.
2313 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2314 msg.obj = prev;
2315 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002316 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 } else {
2318 // This activity failed to schedule the
2319 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002320 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002321 resumeTopActivityLocked(null);
2322 }
2323 }
2324
2325 private final void completePauseLocked() {
2326 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002327 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328
2329 if (prev != null) {
2330 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002331 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2333 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002334 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 if (prev.waitingVisible) {
2336 prev.waitingVisible = false;
2337 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002338 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002339 TAG, "Complete pause, no longer waiting: " + prev);
2340 }
2341 if (prev.configDestroy) {
2342 // The previous is being paused because the configuration
2343 // is changing, which means it is actually stopping...
2344 // To juggle the fact that we are also starting a new
2345 // instance right now, we need to first completely stop
2346 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002347 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002348 destroyActivityLocked(prev, true);
2349 } else {
2350 mStoppingActivities.add(prev);
2351 if (mStoppingActivities.size() > 3) {
2352 // If we already have a few activities waiting to stop,
2353 // then give up on things going idle and start clearing
2354 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002355 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002356 Message msg = Message.obtain();
2357 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2358 mHandler.sendMessage(msg);
2359 }
2360 }
2361 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002362 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 prev = null;
2364 }
2365 mPausingActivity = null;
2366 }
2367
Dianne Hackborn55280a92009-05-07 15:53:46 -07002368 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 resumeTopActivityLocked(prev);
2370 } else {
2371 if (mGoingToSleep.isHeld()) {
2372 mGoingToSleep.release();
2373 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002374 if (mShuttingDown) {
2375 notifyAll();
2376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002377 }
2378
2379 if (prev != null) {
2380 prev.resumeKeyDispatchingLocked();
2381 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002382
2383 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2384 long diff = 0;
2385 synchronized (mProcessStatsThread) {
2386 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2387 }
2388 if (diff > 0) {
2389 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2390 synchronized (bsi) {
2391 BatteryStatsImpl.Uid.Proc ps =
2392 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2393 prev.info.packageName);
2394 if (ps != null) {
2395 ps.addForegroundTimeLocked(diff);
2396 }
2397 }
2398 }
2399 }
2400 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002401 }
2402
2403 /**
2404 * Once we know that we have asked an application to put an activity in
2405 * the resumed state (either by launching it or explicitly telling it),
2406 * this function updates the rest of our state to match that fact.
2407 */
2408 private final void completeResumeLocked(HistoryRecord next) {
2409 next.idle = false;
2410 next.results = null;
2411 next.newIntents = null;
2412
2413 // schedule an idle timeout in case the app doesn't do it for us.
2414 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2415 msg.obj = next;
2416 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2417
2418 if (false) {
2419 // The activity was never told to pause, so just keep
2420 // things going as-is. To maintain our own state,
2421 // we need to emulate it coming back and saying it is
2422 // idle.
2423 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2424 msg.obj = next;
2425 mHandler.sendMessage(msg);
2426 }
2427
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002428 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002430 next.thumbnail = null;
2431 setFocusedActivityLocked(next);
2432 next.resumeKeyDispatchingLocked();
2433 ensureActivitiesVisibleLocked(null, 0);
2434 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002435 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002436
2437 // Mark the point when the activity is resuming
2438 // TODO: To be more accurate, the mark should be before the onCreate,
2439 // not after the onResume. But for subsequent starts, onResume is fine.
2440 if (next.app != null) {
2441 synchronized (mProcessStatsThread) {
2442 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2443 }
2444 } else {
2445 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002447 }
2448
2449 /**
2450 * Make sure that all activities that need to be visible (that is, they
2451 * currently can be seen by the user) actually are.
2452 */
2453 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2454 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002455 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002456 TAG, "ensureActivitiesVisible behind " + top
2457 + " configChanges=0x" + Integer.toHexString(configChanges));
2458
2459 // If the top activity is not fullscreen, then we need to
2460 // make sure any activities under it are now visible.
2461 final int count = mHistory.size();
2462 int i = count-1;
2463 while (mHistory.get(i) != top) {
2464 i--;
2465 }
2466 HistoryRecord r;
2467 boolean behindFullscreen = false;
2468 for (; i>=0; i--) {
2469 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002470 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471 TAG, "Make visible? " + r + " finishing=" + r.finishing
2472 + " state=" + r.state);
2473 if (r.finishing) {
2474 continue;
2475 }
2476
2477 final boolean doThisProcess = onlyThisProcess == null
2478 || onlyThisProcess.equals(r.processName);
2479
2480 // First: if this is not the current activity being started, make
2481 // sure it matches the current configuration.
2482 if (r != starting && doThisProcess) {
2483 ensureActivityConfigurationLocked(r, 0);
2484 }
2485
2486 if (r.app == null || r.app.thread == null) {
2487 if (onlyThisProcess == null
2488 || onlyThisProcess.equals(r.processName)) {
2489 // This activity needs to be visible, but isn't even
2490 // running... get it started, but don't resume it
2491 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002492 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002493 TAG, "Start and freeze screen for " + r);
2494 if (r != starting) {
2495 r.startFreezingScreenLocked(r.app, configChanges);
2496 }
2497 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002498 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002499 TAG, "Starting and making visible: " + r);
2500 mWindowManager.setAppVisibility(r, true);
2501 }
2502 if (r != starting) {
2503 startSpecificActivityLocked(r, false, false);
2504 }
2505 }
2506
2507 } else if (r.visible) {
2508 // If this activity is already visible, then there is nothing
2509 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002510 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511 TAG, "Skipping: already visible at " + r);
2512 r.stopFreezingScreenLocked(false);
2513
2514 } else if (onlyThisProcess == null) {
2515 // This activity is not currently visible, but is running.
2516 // Tell it to become visible.
2517 r.visible = true;
2518 if (r.state != ActivityState.RESUMED && r != starting) {
2519 // If this activity is paused, tell it
2520 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002521 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002522 TAG, "Making visible and scheduling visibility: " + r);
2523 try {
2524 mWindowManager.setAppVisibility(r, true);
2525 r.app.thread.scheduleWindowVisibility(r, true);
2526 r.stopFreezingScreenLocked(false);
2527 } catch (Exception e) {
2528 // Just skip on any failure; we'll make it
2529 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002530 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002531 + r.intent.getComponent(), e);
2532 }
2533 }
2534 }
2535
2536 // Aggregate current change flags.
2537 configChanges |= r.configChangeFlags;
2538
2539 if (r.fullscreen) {
2540 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002541 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 TAG, "Stopping: fullscreen at " + r);
2543 behindFullscreen = true;
2544 i--;
2545 break;
2546 }
2547 }
2548
2549 // Now for any activities that aren't visible to the user, make
2550 // sure they no longer are keeping the screen frozen.
2551 while (i >= 0) {
2552 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002553 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2555 + " state=" + r.state
2556 + " behindFullscreen=" + behindFullscreen);
2557 if (!r.finishing) {
2558 if (behindFullscreen) {
2559 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002560 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 TAG, "Making invisible: " + r);
2562 r.visible = false;
2563 try {
2564 mWindowManager.setAppVisibility(r, false);
2565 if ((r.state == ActivityState.STOPPING
2566 || r.state == ActivityState.STOPPED)
2567 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002568 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 TAG, "Scheduling invisibility: " + r);
2570 r.app.thread.scheduleWindowVisibility(r, false);
2571 }
2572 } catch (Exception e) {
2573 // Just skip on any failure; we'll make it
2574 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002575 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576 + r.intent.getComponent(), e);
2577 }
2578 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002579 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 TAG, "Already invisible: " + r);
2581 }
2582 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002583 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 TAG, "Now behindFullscreen: " + r);
2585 behindFullscreen = true;
2586 }
2587 }
2588 i--;
2589 }
2590 }
2591
2592 /**
2593 * Version of ensureActivitiesVisible that can easily be called anywhere.
2594 */
2595 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2596 int configChanges) {
2597 HistoryRecord r = topRunningActivityLocked(null);
2598 if (r != null) {
2599 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2600 }
2601 }
2602
2603 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2604 if (resumed) {
2605 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2606 } else {
2607 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2608 }
2609 }
2610
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002611 private boolean startHomeActivityLocked() {
2612 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2613 && mTopAction == null) {
2614 // We are running in factory test mode, but unable to find
2615 // the factory test app, so just sit around displaying the
2616 // error message and don't try to start anything.
2617 return false;
2618 }
2619 Intent intent = new Intent(
2620 mTopAction,
2621 mTopData != null ? Uri.parse(mTopData) : null);
2622 intent.setComponent(mTopComponent);
2623 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2624 intent.addCategory(Intent.CATEGORY_HOME);
2625 }
2626 ActivityInfo aInfo =
2627 intent.resolveActivityInfo(mContext.getPackageManager(),
2628 STOCK_PM_FLAGS);
2629 if (aInfo != null) {
2630 intent.setComponent(new ComponentName(
2631 aInfo.applicationInfo.packageName, aInfo.name));
2632 // Don't do this if the home app is currently being
2633 // instrumented.
2634 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2635 aInfo.applicationInfo.uid);
2636 if (app == null || app.instrumentationClass == null) {
2637 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2638 startActivityLocked(null, intent, null, null, 0, aInfo,
2639 null, null, 0, 0, 0, false, false);
2640 }
2641 }
2642
2643
2644 return true;
2645 }
2646
2647 /**
2648 * Starts the "new version setup screen" if appropriate.
2649 */
2650 private void startSetupActivityLocked() {
2651 // Only do this once per boot.
2652 if (mCheckedForSetup) {
2653 return;
2654 }
2655
2656 // We will show this screen if the current one is a different
2657 // version than the last one shown, and we are not running in
2658 // low-level factory test mode.
2659 final ContentResolver resolver = mContext.getContentResolver();
2660 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2661 Settings.Secure.getInt(resolver,
2662 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2663 mCheckedForSetup = true;
2664
2665 // See if we should be showing the platform update setup UI.
2666 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2667 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2668 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2669
2670 // We don't allow third party apps to replace this.
2671 ResolveInfo ri = null;
2672 for (int i=0; ris != null && i<ris.size(); i++) {
2673 if ((ris.get(i).activityInfo.applicationInfo.flags
2674 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2675 ri = ris.get(i);
2676 break;
2677 }
2678 }
2679
2680 if (ri != null) {
2681 String vers = ri.activityInfo.metaData != null
2682 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2683 : null;
2684 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2685 vers = ri.activityInfo.applicationInfo.metaData.getString(
2686 Intent.METADATA_SETUP_VERSION);
2687 }
2688 String lastVers = Settings.Secure.getString(
2689 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2690 if (vers != null && !vers.equals(lastVers)) {
2691 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2692 intent.setComponent(new ComponentName(
2693 ri.activityInfo.packageName, ri.activityInfo.name));
2694 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2695 null, null, 0, 0, 0, false, false);
2696 }
2697 }
2698 }
2699 }
2700
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002701 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002702 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002703
2704 final int identHash = System.identityHashCode(r);
2705 updateUsageStats(r, true);
2706
2707 int i = mWatchers.beginBroadcast();
2708 while (i > 0) {
2709 i--;
2710 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2711 if (w != null) {
2712 try {
2713 w.activityResuming(identHash);
2714 } catch (RemoteException e) {
2715 }
2716 }
2717 }
2718 mWatchers.finishBroadcast();
2719 }
2720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 /**
2722 * Ensure that the top activity in the stack is resumed.
2723 *
2724 * @param prev The previously resumed activity, for when in the process
2725 * of pausing; can be null to call from elsewhere.
2726 *
2727 * @return Returns true if something is being resumed, or false if
2728 * nothing happened.
2729 */
2730 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2731 // Find the first activity that is not finishing.
2732 HistoryRecord next = topRunningActivityLocked(null);
2733
2734 // Remember how we'll process this pause/resume situation, and ensure
2735 // that the state is reset however we wind up proceeding.
2736 final boolean userLeaving = mUserLeaving;
2737 mUserLeaving = false;
2738
2739 if (next == null) {
2740 // There are no more activities! Let's just start up the
2741 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002742 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002743 }
2744
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002745 next.delayedResume = false;
2746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002747 // If the top activity is the resumed one, nothing to do.
2748 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2749 // Make sure we have executed any pending transitions, since there
2750 // should be nothing left to do at this point.
2751 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002752 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002753 return false;
2754 }
2755
2756 // If we are sleeping, and there is no resumed activity, and the top
2757 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002758 if ((mSleeping || mShuttingDown)
2759 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002760 // Make sure we have executed any pending transitions, since there
2761 // should be nothing left to do at this point.
2762 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002763 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002764 return false;
2765 }
2766
2767 // The activity may be waiting for stop, but that is no longer
2768 // appropriate for it.
2769 mStoppingActivities.remove(next);
2770 mWaitingVisibleActivities.remove(next);
2771
Joe Onorato8a9b2202010-02-26 18:56:32 -08002772 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002773
2774 // If we are currently pausing an activity, then don't do anything
2775 // until that is done.
2776 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002777 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002778 return false;
2779 }
2780
2781 // We need to start pausing the current activity so the top one
2782 // can be resumed...
2783 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002784 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002785 startPausingLocked(userLeaving, false);
2786 return true;
2787 }
2788
2789 if (prev != null && prev != next) {
2790 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2791 prev.waitingVisible = true;
2792 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002793 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002794 TAG, "Resuming top, waiting visible to hide: " + prev);
2795 } else {
2796 // The next activity is already visible, so hide the previous
2797 // activity's windows right now so we can show the new one ASAP.
2798 // We only do this if the previous is finishing, which should mean
2799 // it is on top of the one being resumed so hiding it quickly
2800 // is good. Otherwise, we want to do the normal route of allowing
2801 // the resumed activity to be shown so we can decide if the
2802 // previous should actually be hidden depending on whether the
2803 // new one is found to be full-screen or not.
2804 if (prev.finishing) {
2805 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002806 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002807 + prev + ", waitingVisible="
2808 + (prev != null ? prev.waitingVisible : null)
2809 + ", nowVisible=" + next.nowVisible);
2810 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002811 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002812 + prev + ", waitingVisible="
2813 + (prev != null ? prev.waitingVisible : null)
2814 + ", nowVisible=" + next.nowVisible);
2815 }
2816 }
2817 }
2818
2819 // We are starting up the next activity, so tell the window manager
2820 // that the previous one will be hidden soon. This way it can know
2821 // to ignore it when computing the desired screen orientation.
2822 if (prev != null) {
2823 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002824 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002825 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002826 if (mNoAnimActivities.contains(prev)) {
2827 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2828 } else {
2829 mWindowManager.prepareAppTransition(prev.task == next.task
2830 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2831 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002833 mWindowManager.setAppWillBeHidden(prev);
2834 mWindowManager.setAppVisibility(prev, false);
2835 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002836 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002837 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002838 if (mNoAnimActivities.contains(next)) {
2839 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2840 } else {
2841 mWindowManager.prepareAppTransition(prev.task == next.task
2842 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2843 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002845 }
2846 if (false) {
2847 mWindowManager.setAppWillBeHidden(prev);
2848 mWindowManager.setAppVisibility(prev, false);
2849 }
2850 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002851 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002852 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002853 if (mNoAnimActivities.contains(next)) {
2854 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2855 } else {
2856 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002858 }
2859
2860 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002861 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002862
2863 // This activity is now becoming visible.
2864 mWindowManager.setAppVisibility(next, true);
2865
2866 HistoryRecord lastResumedActivity = mResumedActivity;
2867 ActivityState lastState = next.state;
2868
2869 updateCpuStats();
2870
2871 next.state = ActivityState.RESUMED;
2872 mResumedActivity = next;
2873 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002874 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002875 updateLRUListLocked(next);
2876
2877 // Have the window manager re-evaluate the orientation of
2878 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002879 boolean updated;
2880 synchronized (this) {
2881 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2882 mConfiguration,
2883 next.mayFreezeScreenLocked(next.app) ? next : null);
2884 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002885 next.frozenBeforeDestroy = true;
2886 }
2887 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002889 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002890 // The configuration update wasn't able to keep the existing
2891 // instance of the activity, and instead started a new one.
2892 // We should be all done, but let's just make sure our activity
2893 // is still at the top and schedule another run if something
2894 // weird happened.
2895 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002896 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 "Activity config changed during resume: " + next
2898 + ", new next: " + nextNext);
2899 if (nextNext != next) {
2900 // Do over!
2901 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2902 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002903 setFocusedActivityLocked(next);
2904 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002906 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002907 return true;
2908 }
2909
2910 try {
2911 // Deliver all pending results.
2912 ArrayList a = next.results;
2913 if (a != null) {
2914 final int N = a.size();
2915 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002916 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002917 TAG, "Delivering results to " + next
2918 + ": " + a);
2919 next.app.thread.scheduleSendResult(next, a);
2920 }
2921 }
2922
2923 if (next.newIntents != null) {
2924 next.app.thread.scheduleNewIntent(next.newIntents, next);
2925 }
2926
Doug Zongker2bec3d42009-12-04 12:52:44 -08002927 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 System.identityHashCode(next),
2929 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930
2931 next.app.thread.scheduleResumeActivity(next,
2932 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 pauseIfSleepingLocked();
2935
2936 } catch (Exception e) {
2937 // Whoops, need to restart this activity!
2938 next.state = lastState;
2939 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002940 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 if (!next.hasBeenLaunched) {
2942 next.hasBeenLaunched = true;
2943 } else {
2944 if (SHOW_APP_STARTING_ICON) {
2945 mWindowManager.setAppStartingWindow(
2946 next, next.packageName, next.theme,
2947 next.nonLocalizedLabel,
2948 next.labelRes, next.icon, null, true);
2949 }
2950 }
2951 startSpecificActivityLocked(next, true, false);
2952 return true;
2953 }
2954
2955 // From this point on, if something goes wrong there is no way
2956 // to recover the activity.
2957 try {
2958 next.visible = true;
2959 completeResumeLocked(next);
2960 } catch (Exception e) {
2961 // If any exception gets thrown, toss away this
2962 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002963 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2965 "resume-exception");
2966 return true;
2967 }
2968
2969 // Didn't need to use the icicle, and it is now out of date.
2970 next.icicle = null;
2971 next.haveState = false;
2972 next.stopped = false;
2973
2974 } else {
2975 // Whoops, need to restart this activity!
2976 if (!next.hasBeenLaunched) {
2977 next.hasBeenLaunched = true;
2978 } else {
2979 if (SHOW_APP_STARTING_ICON) {
2980 mWindowManager.setAppStartingWindow(
2981 next, next.packageName, next.theme,
2982 next.nonLocalizedLabel,
2983 next.labelRes, next.icon, null, true);
2984 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002985 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 }
2987 startSpecificActivityLocked(next, true, true);
2988 }
2989
2990 return true;
2991 }
2992
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002993 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2994 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002995 final int NH = mHistory.size();
2996
2997 int addPos = -1;
2998
2999 if (!newTask) {
3000 // If starting in an existing task, find where that is...
3001 HistoryRecord next = null;
3002 boolean startIt = true;
3003 for (int i = NH-1; i >= 0; i--) {
3004 HistoryRecord p = (HistoryRecord)mHistory.get(i);
3005 if (p.finishing) {
3006 continue;
3007 }
3008 if (p.task == r.task) {
3009 // Here it is! Now, if this is not yet visible to the
3010 // user, then just add it without starting; it will
3011 // get started when the user navigates back to it.
3012 addPos = i+1;
3013 if (!startIt) {
3014 mHistory.add(addPos, r);
3015 r.inHistory = true;
3016 r.task.numActivities++;
3017 mWindowManager.addAppToken(addPos, r, r.task.taskId,
3018 r.info.screenOrientation, r.fullscreen);
3019 if (VALIDATE_TOKENS) {
3020 mWindowManager.validateAppTokens(mHistory);
3021 }
3022 return;
3023 }
3024 break;
3025 }
3026 if (p.fullscreen) {
3027 startIt = false;
3028 }
3029 next = p;
3030 }
3031 }
3032
3033 // Place a new activity at top of stack, so it is next to interact
3034 // with the user.
3035 if (addPos < 0) {
3036 addPos = mHistory.size();
3037 }
3038
3039 // If we are not placing the new activity frontmost, we do not want
3040 // to deliver the onUserLeaving callback to the actual frontmost
3041 // activity
3042 if (addPos < NH) {
3043 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003044 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 }
3046
3047 // Slot the activity into the history stack and proceed
3048 mHistory.add(addPos, r);
3049 r.inHistory = true;
3050 r.frontOfTask = newTask;
3051 r.task.numActivities++;
3052 if (NH > 0) {
3053 // We want to show the starting preview window if we are
3054 // switching to a new task, or the next activity's process is
3055 // not currently running.
3056 boolean showStartingIcon = newTask;
3057 ProcessRecord proc = r.app;
3058 if (proc == null) {
3059 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
3060 }
3061 if (proc == null || proc.thread == null) {
3062 showStartingIcon = true;
3063 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003064 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003066 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3067 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
3068 mNoAnimActivities.add(r);
3069 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3070 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
3071 mNoAnimActivities.remove(r);
3072 } else {
3073 mWindowManager.prepareAppTransition(newTask
3074 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
3075 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
3076 mNoAnimActivities.remove(r);
3077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 mWindowManager.addAppToken(
3079 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
3080 boolean doShow = true;
3081 if (newTask) {
3082 // Even though this activity is starting fresh, we still need
3083 // to reset it to make sure we apply affinities to move any
3084 // existing activities from other tasks in to it.
3085 // If the caller has requested that the target task be
3086 // reset, then do so.
3087 if ((r.intent.getFlags()
3088 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3089 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003090 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003091 }
3092 }
3093 if (SHOW_APP_STARTING_ICON && doShow) {
3094 // Figure out if we are transitioning from another activity that is
3095 // "has the same starting icon" as the next one. This allows the
3096 // window manager to keep the previous window it had previously
3097 // created, if it still had one.
3098 HistoryRecord prev = mResumedActivity;
3099 if (prev != null) {
3100 // We don't want to reuse the previous starting preview if:
3101 // (1) The current activity is in a different task.
3102 if (prev.task != r.task) prev = null;
3103 // (2) The current activity is already displayed.
3104 else if (prev.nowVisible) prev = null;
3105 }
3106 mWindowManager.setAppStartingWindow(
3107 r, r.packageName, r.theme, r.nonLocalizedLabel,
3108 r.labelRes, r.icon, prev, showStartingIcon);
3109 }
3110 } else {
3111 // If this is the first activity, don't do any fancy animations,
3112 // because there is nothing for it to animate on top of.
3113 mWindowManager.addAppToken(addPos, r, r.task.taskId,
3114 r.info.screenOrientation, r.fullscreen);
3115 }
3116 if (VALIDATE_TOKENS) {
3117 mWindowManager.validateAppTokens(mHistory);
3118 }
3119
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003120 if (doResume) {
3121 resumeTopActivityLocked(null);
3122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003123 }
3124
3125 /**
3126 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003127 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
3128 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003129 * an instance of that activity in the stack and, if found, finish all
3130 * activities on top of it and return the instance.
3131 *
3132 * @param newR Description of the new activity being started.
3133 * @return Returns the old activity that should be continue to be used,
3134 * or null if none was found.
3135 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003136 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003137 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003139
3140 // First find the requested task.
3141 while (i > 0) {
3142 i--;
3143 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3144 if (r.task.taskId == taskId) {
3145 i++;
3146 break;
3147 }
3148 }
3149
3150 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003151 while (i > 0) {
3152 i--;
3153 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3154 if (r.finishing) {
3155 continue;
3156 }
3157 if (r.task.taskId != taskId) {
3158 return null;
3159 }
3160 if (r.realActivity.equals(newR.realActivity)) {
3161 // Here it is! Now finish everything in front...
3162 HistoryRecord ret = r;
3163 if (doClear) {
3164 while (i < (mHistory.size()-1)) {
3165 i++;
3166 r = (HistoryRecord)mHistory.get(i);
3167 if (r.finishing) {
3168 continue;
3169 }
3170 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3171 null, "clear")) {
3172 i--;
3173 }
3174 }
3175 }
3176
3177 // Finally, if this is a normal launch mode (that is, not
3178 // expecting onNewIntent()), then we will finish the current
3179 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003180 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
3181 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003182 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003183 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003184 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07003185 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003186 null, "clear");
3187 }
3188 return null;
3189 }
3190 }
3191
3192 return ret;
3193 }
3194 }
3195
3196 return null;
3197 }
3198
3199 /**
3200 * Find the activity in the history stack within the given task. Returns
3201 * the index within the history at which it's found, or < 0 if not found.
3202 */
3203 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3204 int i = mHistory.size();
3205 while (i > 0) {
3206 i--;
3207 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3208 if (candidate.task.taskId != task) {
3209 break;
3210 }
3211 if (candidate.realActivity.equals(r.realActivity)) {
3212 return i;
3213 }
3214 }
3215
3216 return -1;
3217 }
3218
3219 /**
3220 * Reorder the history stack so that the activity at the given index is
3221 * brought to the front.
3222 */
3223 private final HistoryRecord moveActivityToFrontLocked(int where) {
3224 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3225 int top = mHistory.size();
3226 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3227 mHistory.add(top, newTop);
3228 oldTop.frontOfTask = false;
3229 newTop.frontOfTask = true;
3230 return newTop;
3231 }
3232
3233 /**
3234 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3235 * method will be called at the proper time.
3236 */
3237 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3238 boolean sent = false;
3239 if (r.state == ActivityState.RESUMED
3240 && r.app != null && r.app.thread != null) {
3241 try {
3242 ArrayList<Intent> ar = new ArrayList<Intent>();
3243 ar.add(new Intent(intent));
3244 r.app.thread.scheduleNewIntent(ar, r);
3245 sent = true;
3246 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003247 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 }
3249 }
3250 if (!sent) {
3251 r.addNewIntentLocked(new Intent(intent));
3252 }
3253 }
3254
3255 private final void logStartActivity(int tag, HistoryRecord r,
3256 TaskRecord task) {
3257 EventLog.writeEvent(tag,
3258 System.identityHashCode(r), task.taskId,
3259 r.shortComponentName, r.intent.getAction(),
3260 r.intent.getType(), r.intent.getDataString(),
3261 r.intent.getFlags());
3262 }
3263
3264 private final int startActivityLocked(IApplicationThread caller,
3265 Intent intent, String resolvedType,
3266 Uri[] grantedUriPermissions,
3267 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3268 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003269 int callingPid, int callingUid, boolean onlyIfNeeded,
3270 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003271 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003272
3273 HistoryRecord sourceRecord = null;
3274 HistoryRecord resultRecord = null;
3275 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003276 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003277 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3279 if (index >= 0) {
3280 sourceRecord = (HistoryRecord)mHistory.get(index);
3281 if (requestCode >= 0 && !sourceRecord.finishing) {
3282 resultRecord = sourceRecord;
3283 }
3284 }
3285 }
3286
3287 int launchFlags = intent.getFlags();
3288
3289 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3290 && sourceRecord != null) {
3291 // Transfer the result target from the source activity to the new
3292 // one being started, including any failures.
3293 if (requestCode >= 0) {
3294 return START_FORWARD_AND_REQUEST_CONFLICT;
3295 }
3296 resultRecord = sourceRecord.resultTo;
3297 resultWho = sourceRecord.resultWho;
3298 requestCode = sourceRecord.requestCode;
3299 sourceRecord.resultTo = null;
3300 if (resultRecord != null) {
3301 resultRecord.removeResultsLocked(
3302 sourceRecord, resultWho, requestCode);
3303 }
3304 }
3305
3306 int err = START_SUCCESS;
3307
3308 if (intent.getComponent() == null) {
3309 // We couldn't find a class that can handle the given Intent.
3310 // That's the end of that!
3311 err = START_INTENT_NOT_RESOLVED;
3312 }
3313
3314 if (err == START_SUCCESS && aInfo == null) {
3315 // We couldn't find the specific class specified in the Intent.
3316 // Also the end of the line.
3317 err = START_CLASS_NOT_FOUND;
3318 }
3319
3320 ProcessRecord callerApp = null;
3321 if (err == START_SUCCESS && caller != null) {
3322 callerApp = getRecordForAppLocked(caller);
3323 if (callerApp != null) {
3324 callingPid = callerApp.pid;
3325 callingUid = callerApp.info.uid;
3326 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003327 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328 + " (pid=" + callingPid + ") when starting: "
3329 + intent.toString());
3330 err = START_PERMISSION_DENIED;
3331 }
3332 }
3333
3334 if (err != START_SUCCESS) {
3335 if (resultRecord != null) {
3336 sendActivityResultLocked(-1,
3337 resultRecord, resultWho, requestCode,
3338 Activity.RESULT_CANCELED, null);
3339 }
3340 return err;
3341 }
3342
3343 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3344 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3345 if (perm != PackageManager.PERMISSION_GRANTED) {
3346 if (resultRecord != null) {
3347 sendActivityResultLocked(-1,
3348 resultRecord, resultWho, requestCode,
3349 Activity.RESULT_CANCELED, null);
3350 }
3351 String msg = "Permission Denial: starting " + intent.toString()
3352 + " from " + callerApp + " (pid=" + callingPid
3353 + ", uid=" + callingUid + ")"
3354 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003355 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003356 throw new SecurityException(msg);
3357 }
3358
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003359 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003360 boolean abort = false;
3361 try {
3362 // The Intent we give to the watcher has the extra data
3363 // stripped off, since it can contain private information.
3364 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003365 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366 aInfo.applicationInfo.packageName);
3367 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003368 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003369 }
3370
3371 if (abort) {
3372 if (resultRecord != null) {
3373 sendActivityResultLocked(-1,
3374 resultRecord, resultWho, requestCode,
3375 Activity.RESULT_CANCELED, null);
3376 }
3377 // We pretend to the caller that it was really started, but
3378 // they will just get a cancel result.
3379 return START_SUCCESS;
3380 }
3381 }
3382
3383 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3384 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003385 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003386
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003387 if (mResumedActivity == null
3388 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3389 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3390 PendingActivityLaunch pal = new PendingActivityLaunch();
3391 pal.r = r;
3392 pal.sourceRecord = sourceRecord;
3393 pal.grantedUriPermissions = grantedUriPermissions;
3394 pal.grantedMode = grantedMode;
3395 pal.onlyIfNeeded = onlyIfNeeded;
3396 mPendingActivityLaunches.add(pal);
3397 return START_SWITCHES_CANCELED;
3398 }
3399 }
3400
3401 if (mDidAppSwitch) {
3402 // This is the second allowed switch since we stopped switches,
3403 // so now just generally allow switches. Use case: user presses
3404 // home (switches disabled, switch to home, mDidAppSwitch now true);
3405 // user taps a home icon (coming from home so allowed, we hit here
3406 // and now allow anyone to switch again).
3407 mAppSwitchesAllowedTime = 0;
3408 } else {
3409 mDidAppSwitch = true;
3410 }
3411
3412 doPendingActivityLaunchesLocked(false);
3413
3414 return startActivityUncheckedLocked(r, sourceRecord,
3415 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3416 }
3417
3418 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3419 final int N = mPendingActivityLaunches.size();
3420 if (N <= 0) {
3421 return;
3422 }
3423 for (int i=0; i<N; i++) {
3424 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3425 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3426 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3427 doResume && i == (N-1));
3428 }
3429 mPendingActivityLaunches.clear();
3430 }
3431
3432 private final int startActivityUncheckedLocked(HistoryRecord r,
3433 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3434 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3435 final Intent intent = r.intent;
3436 final int callingUid = r.launchedFromUid;
3437
3438 int launchFlags = intent.getFlags();
3439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 // We'll invoke onUserLeaving before onPause only if the launching
3441 // activity did not explicitly state that this is an automated launch.
3442 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003443 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444 "startActivity() => mUserLeaving=" + mUserLeaving);
3445
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003446 // If the caller has asked not to resume at this point, we make note
3447 // of this in the record so that we can skip it when trying to find
3448 // the top running activity.
3449 if (!doResume) {
3450 r.delayedResume = true;
3451 }
3452
3453 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3454 != 0 ? r : null;
3455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 // If the onlyIfNeeded flag is set, then we can do this if the activity
3457 // being launched is the same as the one making the call... or, as
3458 // a special case, if we do not know the caller then we count the
3459 // current top activity as the caller.
3460 if (onlyIfNeeded) {
3461 HistoryRecord checkedCaller = sourceRecord;
3462 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003463 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 }
3465 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3466 // Caller is not the same as launcher, so always needed.
3467 onlyIfNeeded = false;
3468 }
3469 }
3470
3471 if (grantedUriPermissions != null && callingUid > 0) {
3472 for (int i=0; i<grantedUriPermissions.length; i++) {
3473 grantUriPermissionLocked(callingUid, r.packageName,
3474 grantedUriPermissions[i], grantedMode, r);
3475 }
3476 }
3477
3478 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3479 intent, r);
3480
3481 if (sourceRecord == null) {
3482 // This activity is not being started from another... in this
3483 // case we -always- start a new task.
3484 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003485 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 -08003486 + intent);
3487 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3488 }
3489 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3490 // The original activity who is starting us is running as a single
3491 // instance... this new activity it is starting must go on its
3492 // own task.
3493 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3494 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3495 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3496 // The activity being started is a single instance... it always
3497 // gets launched into its own task.
3498 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3499 }
3500
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003501 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 // For whatever reason this activity is being launched into a new
3503 // task... yet the caller has requested a result back. Well, that
3504 // is pretty messed up, so instead immediately send back a cancel
3505 // and let the new task continue launched as normal without a
3506 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003507 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003508 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003509 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510 Activity.RESULT_CANCELED, null);
3511 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003512 }
3513
3514 boolean addingToTask = false;
3515 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3516 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3517 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3518 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3519 // If bring to front is requested, and no result is requested, and
3520 // we can find a task that was started with this same
3521 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003522 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 // See if there is a task to bring to the front. If this is
3524 // a SINGLE_INSTANCE activity, there can be one and only one
3525 // instance of it in the history, and it is always in its own
3526 // unique task, so we do a special search.
3527 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3528 ? findTaskLocked(intent, r.info)
3529 : findActivityLocked(intent, r.info);
3530 if (taskTop != null) {
3531 if (taskTop.task.intent == null) {
3532 // This task was started because of movement of
3533 // the activity based on affinity... now that we
3534 // are actually launching it, we can assign the
3535 // base intent.
3536 taskTop.task.setIntent(intent, r.info);
3537 }
3538 // If the target task is not in the front, then we need
3539 // to bring it to the front... except... well, with
3540 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3541 // to have the same behavior as if a new instance was
3542 // being started, which means not bringing it to the front
3543 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003544 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545 if (curTop.task != taskTop.task) {
3546 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3547 boolean callerAtFront = sourceRecord == null
3548 || curTop.task == sourceRecord.task;
3549 if (callerAtFront) {
3550 // We really do want to push this one into the
3551 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003552 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003553 }
3554 }
3555 // If the caller has requested that the target task be
3556 // reset, then do so.
3557 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3558 taskTop = resetTaskIfNeededLocked(taskTop, r);
3559 }
3560 if (onlyIfNeeded) {
3561 // We don't need to start a new activity, and
3562 // the client said not to do anything if that
3563 // is the case, so this is it! And for paranoia, make
3564 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003565 if (doResume) {
3566 resumeTopActivityLocked(null);
3567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 return START_RETURN_INTENT_TO_CALLER;
3569 }
3570 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3571 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3572 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3573 // In this situation we want to remove all activities
3574 // from the task up to the one being started. In most
3575 // cases this means we are resetting the task to its
3576 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003577 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003578 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003579 if (top != null) {
3580 if (top.frontOfTask) {
3581 // Activity aliases may mean we use different
3582 // intents for the top activity, so make sure
3583 // the task now has the identity of the new
3584 // intent.
3585 top.task.setIntent(r.intent, r.info);
3586 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003587 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003588 deliverNewIntentLocked(top, r.intent);
3589 } else {
3590 // A special case: we need to
3591 // start the activity because it is not currently
3592 // running, and the caller has asked to clear the
3593 // current task to have this activity at the top.
3594 addingToTask = true;
3595 // Now pretend like this activity is being started
3596 // by the top of its task, so it is put in the
3597 // right place.
3598 sourceRecord = taskTop;
3599 }
3600 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3601 // In this case the top activity on the task is the
3602 // same as the one being launched, so we take that
3603 // as a request to bring the task to the foreground.
3604 // If the top activity in the task is the root
3605 // activity, deliver this new intent to it if it
3606 // desires.
3607 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3608 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003609 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 if (taskTop.frontOfTask) {
3611 taskTop.task.setIntent(r.intent, r.info);
3612 }
3613 deliverNewIntentLocked(taskTop, r.intent);
3614 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3615 // In this case we are launching the root activity
3616 // of the task, but with a different intent. We
3617 // should start a new instance on top.
3618 addingToTask = true;
3619 sourceRecord = taskTop;
3620 }
3621 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3622 // In this case an activity is being launched in to an
3623 // existing task, without resetting that task. This
3624 // is typically the situation of launching an activity
3625 // from a notification or shortcut. We want to place
3626 // the new activity on top of the current task.
3627 addingToTask = true;
3628 sourceRecord = taskTop;
3629 } else if (!taskTop.task.rootWasReset) {
3630 // In this case we are launching in to an existing task
3631 // that has not yet been started from its front door.
3632 // The current task has been brought to the front.
3633 // Ideally, we'd probably like to place this new task
3634 // at the bottom of its stack, but that's a little hard
3635 // to do with the current organization of the code so
3636 // for now we'll just drop it.
3637 taskTop.task.setIntent(r.intent, r.info);
3638 }
3639 if (!addingToTask) {
3640 // We didn't do anything... but it was needed (a.k.a., client
3641 // don't use that intent!) And for paranoia, make
3642 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003643 if (doResume) {
3644 resumeTopActivityLocked(null);
3645 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003646 return START_TASK_TO_FRONT;
3647 }
3648 }
3649 }
3650 }
3651
3652 //String uri = r.intent.toURI();
3653 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003654 //Slog.i(TAG, "Given intent: " + r.intent);
3655 //Slog.i(TAG, "URI is: " + uri);
3656 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003657
3658 if (r.packageName != null) {
3659 // If the activity being launched is the same as the one currently
3660 // at the top, then we need to check if it should only be launched
3661 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003662 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3663 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 if (top.realActivity.equals(r.realActivity)) {
3665 if (top.app != null && top.app.thread != null) {
3666 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3667 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3668 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003669 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003670 // For paranoia, make sure we have correctly
3671 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003672 if (doResume) {
3673 resumeTopActivityLocked(null);
3674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003675 if (onlyIfNeeded) {
3676 // We don't need to start a new activity, and
3677 // the client said not to do anything if that
3678 // is the case, so this is it!
3679 return START_RETURN_INTENT_TO_CALLER;
3680 }
3681 deliverNewIntentLocked(top, r.intent);
3682 return START_DELIVERED_TO_TOP;
3683 }
3684 }
3685 }
3686 }
3687
3688 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003689 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003690 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003691 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003692 Activity.RESULT_CANCELED, null);
3693 }
3694 return START_CLASS_NOT_FOUND;
3695 }
3696
3697 boolean newTask = false;
3698
3699 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003700 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3702 // todo: should do better management of integers.
3703 mCurTask++;
3704 if (mCurTask <= 0) {
3705 mCurTask = 1;
3706 }
3707 r.task = new TaskRecord(mCurTask, r.info, intent,
3708 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003709 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 + " in new task " + r.task);
3711 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003712 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713
3714 } else if (sourceRecord != null) {
3715 if (!addingToTask &&
3716 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3717 // In this case, we are adding the activity to an existing
3718 // task, but the caller has asked to clear that task if the
3719 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003720 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003721 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003722 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003723 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003724 deliverNewIntentLocked(top, r.intent);
3725 // For paranoia, make sure we have correctly
3726 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003727 if (doResume) {
3728 resumeTopActivityLocked(null);
3729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003730 return START_DELIVERED_TO_TOP;
3731 }
3732 } else if (!addingToTask &&
3733 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3734 // In this case, we are launching an activity in our own task
3735 // that may already be running somewhere in the history, and
3736 // we want to shuffle it to the front of the stack if so.
3737 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3738 if (where >= 0) {
3739 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003740 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003742 if (doResume) {
3743 resumeTopActivityLocked(null);
3744 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 return START_DELIVERED_TO_TOP;
3746 }
3747 }
3748 // An existing activity is starting this new activity, so we want
3749 // to keep the new one in the same task as the one that is starting
3750 // it.
3751 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003752 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003753 + " in existing task " + r.task);
3754
3755 } else {
3756 // This not being started from an existing activity, and not part
3757 // of a new task... just put it in the top task, though these days
3758 // this case should never happen.
3759 final int N = mHistory.size();
3760 HistoryRecord prev =
3761 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3762 r.task = prev != null
3763 ? prev.task
3764 : new TaskRecord(mCurTask, r.info, intent,
3765 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003766 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 + " in new guessed " + r.task);
3768 }
3769 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003770 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003771 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003772 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003773 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003774 return START_SUCCESS;
3775 }
3776
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003777 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3778 long thisTime, long totalTime) {
3779 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3780 WaitResult w = mWaitingActivityLaunched.get(i);
3781 w.timeout = timeout;
3782 if (r != null) {
3783 w.who = new ComponentName(r.info.packageName, r.info.name);
3784 }
3785 w.thisTime = thisTime;
3786 w.totalTime = totalTime;
3787 }
3788 notify();
3789 }
3790
3791 void reportActivityVisibleLocked(HistoryRecord r) {
3792 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3793 WaitResult w = mWaitingActivityVisible.get(i);
3794 w.timeout = false;
3795 if (r != null) {
3796 w.who = new ComponentName(r.info.packageName, r.info.name);
3797 }
3798 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3799 w.thisTime = w.totalTime;
3800 }
3801 notify();
3802 }
3803
3804 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3806 int grantedMode, IBinder resultTo,
3807 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003808 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003809 // Refuse possible leaked file descriptors
3810 if (intent != null && intent.hasFileDescriptors()) {
3811 throw new IllegalArgumentException("File descriptors passed in Intent");
3812 }
3813
Dianne Hackborn860755f2010-06-03 18:47:52 -07003814 boolean componentSpecified = intent.getComponent() != null;
The Android Open Source Project4df24232009-03-05 14:34:35 -08003815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816 // Don't modify the client's object!
3817 intent = new Intent(intent);
3818
3819 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 ActivityInfo aInfo;
3821 try {
3822 ResolveInfo rInfo =
3823 ActivityThread.getPackageManager().resolveIntent(
3824 intent, resolvedType,
3825 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003826 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 aInfo = rInfo != null ? rInfo.activityInfo : null;
3828 } catch (RemoteException e) {
3829 aInfo = null;
3830 }
3831
3832 if (aInfo != null) {
3833 // Store the found target back into the intent, because now that
3834 // we have it we never want to do this again. For example, if the
3835 // user navigates back to this point in the history, we should
3836 // always restart the exact same activity.
3837 intent.setComponent(new ComponentName(
3838 aInfo.applicationInfo.packageName, aInfo.name));
3839
3840 // Don't debug things in the system process
3841 if (debug) {
3842 if (!aInfo.processName.equals("system")) {
3843 setDebugApp(aInfo.processName, true, false);
3844 }
3845 }
3846 }
3847
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003848 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003849 int callingPid;
3850 int callingUid;
3851 if (caller == null) {
3852 callingPid = Binder.getCallingPid();
3853 callingUid = Binder.getCallingUid();
3854 } else {
3855 callingPid = callingUid = -1;
3856 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003857
3858 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003859 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3860 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003863
Dianne Hackborn860755f2010-06-03 18:47:52 -07003864 if (aInfo != null &&
3865 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
3866 // This may be a heavy-weight process! Check to see if we already
3867 // have another, different heavy-weight process running.
3868 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
3869 if (mHeavyWeightProcess != null &&
3870 (mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
3871 !mHeavyWeightProcess.processName.equals(aInfo.processName))) {
3872 int realCallingPid = callingPid;
3873 int realCallingUid = callingUid;
3874 if (caller != null) {
3875 ProcessRecord callerApp = getRecordForAppLocked(caller);
3876 if (callerApp != null) {
3877 realCallingPid = callerApp.pid;
3878 realCallingUid = callerApp.info.uid;
3879 } else {
3880 Slog.w(TAG, "Unable to find app for caller " + caller
3881 + " (pid=" + realCallingPid + ") when starting: "
3882 + intent.toString());
3883 return START_PERMISSION_DENIED;
3884 }
3885 }
3886
3887 IIntentSender target = getIntentSenderLocked(
3888 IActivityManager.INTENT_SENDER_ACTIVITY, "android",
3889 realCallingUid, null, null, 0, intent,
3890 resolvedType, PendingIntent.FLAG_CANCEL_CURRENT
3891 | PendingIntent.FLAG_ONE_SHOT);
3892
3893 Intent newIntent = new Intent();
3894 if (requestCode >= 0) {
3895 // Caller is requesting a result.
3896 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3897 }
3898 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
3899 new IntentSender(target));
3900 if (mHeavyWeightProcess.activities.size() > 0) {
3901 HistoryRecord hist = mHeavyWeightProcess.activities.get(0);
3902 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
3903 hist.packageName);
3904 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3905 hist.task.taskId);
3906 }
3907 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3908 aInfo.packageName);
3909 newIntent.setFlags(intent.getFlags());
3910 newIntent.setClassName("android",
3911 HeavyWeightSwitcherActivity.class.getName());
3912 intent = newIntent;
3913 resolvedType = null;
3914 caller = null;
3915 callingUid = Binder.getCallingUid();
3916 callingPid = Binder.getCallingPid();
3917 componentSpecified = true;
3918 try {
3919 ResolveInfo rInfo =
3920 ActivityThread.getPackageManager().resolveIntent(
3921 intent, null,
3922 PackageManager.MATCH_DEFAULT_ONLY
3923 | STOCK_PM_FLAGS);
3924 aInfo = rInfo != null ? rInfo.activityInfo : null;
3925 } catch (RemoteException e) {
3926 aInfo = null;
3927 }
3928 }
3929 }
3930 }
3931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 int res = startActivityLocked(caller, intent, resolvedType,
3933 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003934 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003935 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003936
Dianne Hackborne2522462010-03-29 18:41:30 -07003937 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003938 // If the caller also wants to switch to a new configuration,
3939 // do so now. This allows a clean switch, as we are waiting
3940 // for the current activity to pause (so we will not destroy
3941 // it), and have not yet started the next activity.
3942 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3943 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003944 mConfigWillChange = false;
3945 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3946 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003947 updateConfigurationLocked(config, null);
3948 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003951
3952 if (outResult != null) {
3953 outResult.result = res;
3954 if (res == IActivityManager.START_SUCCESS) {
3955 mWaitingActivityLaunched.add(outResult);
3956 do {
3957 try {
3958 wait();
3959 } catch (InterruptedException e) {
3960 }
3961 } while (!outResult.timeout && outResult.who == null);
3962 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3963 HistoryRecord r = this.topRunningActivityLocked(null);
3964 if (r.nowVisible) {
3965 outResult.timeout = false;
3966 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3967 outResult.totalTime = 0;
3968 outResult.thisTime = 0;
3969 } else {
3970 outResult.thisTime = SystemClock.uptimeMillis();
3971 mWaitingActivityVisible.add(outResult);
3972 do {
3973 try {
3974 wait();
3975 } catch (InterruptedException e) {
3976 }
3977 } while (!outResult.timeout && outResult.who == null);
3978 }
3979 }
3980 }
3981
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003982 return res;
3983 }
3984 }
3985
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003986 public final int startActivity(IApplicationThread caller,
3987 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3988 int grantedMode, IBinder resultTo,
3989 String resultWho, int requestCode, boolean onlyIfNeeded,
3990 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003991 return startActivityMayWait(caller, intent, resolvedType,
3992 grantedUriPermissions, grantedMode, resultTo, resultWho,
3993 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003994 }
3995
3996 public final WaitResult startActivityAndWait(IApplicationThread caller,
3997 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3998 int grantedMode, IBinder resultTo,
3999 String resultWho, int requestCode, boolean onlyIfNeeded,
4000 boolean debug) {
4001 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07004002 startActivityMayWait(caller, intent, resolvedType,
4003 grantedUriPermissions, grantedMode, resultTo, resultWho,
4004 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08004005 return res;
4006 }
4007
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07004008 public final int startActivityWithConfig(IApplicationThread caller,
4009 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
4010 int grantedMode, IBinder resultTo,
4011 String resultWho, int requestCode, boolean onlyIfNeeded,
4012 boolean debug, Configuration config) {
4013 return startActivityMayWait(caller, intent, resolvedType,
4014 grantedUriPermissions, grantedMode, resultTo, resultWho,
4015 requestCode, onlyIfNeeded, debug, null, config);
4016 }
4017
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08004018 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07004019 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07004020 IBinder resultTo, String resultWho, int requestCode,
4021 int flagsMask, int flagsValues) {
4022 // Refuse possible leaked file descriptors
4023 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
4024 throw new IllegalArgumentException("File descriptors passed in Intent");
4025 }
4026
4027 IIntentSender sender = intent.getTarget();
4028 if (!(sender instanceof PendingIntentRecord)) {
4029 throw new IllegalArgumentException("Bad PendingIntent object");
4030 }
4031
4032 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07004033
4034 synchronized (this) {
4035 // If this is coming from the currently resumed activity, it is
4036 // effectively saying that app switches are allowed at this point.
4037 if (mResumedActivity != null
4038 && mResumedActivity.info.applicationInfo.uid ==
4039 Binder.getCallingUid()) {
4040 mAppSwitchesAllowedTime = 0;
4041 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07004042 }
4043
4044 return pir.sendInner(0, fillInIntent, resolvedType,
4045 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
4046 }
4047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004048 public boolean startNextMatchingActivity(IBinder callingActivity,
4049 Intent intent) {
4050 // Refuse possible leaked file descriptors
4051 if (intent != null && intent.hasFileDescriptors() == true) {
4052 throw new IllegalArgumentException("File descriptors passed in Intent");
4053 }
4054
4055 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004056 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057 if (index < 0) {
4058 return false;
4059 }
4060 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4061 if (r.app == null || r.app.thread == null) {
4062 // The caller is not running... d'oh!
4063 return false;
4064 }
4065 intent = new Intent(intent);
4066 // The caller is not allowed to change the data.
4067 intent.setDataAndType(r.intent.getData(), r.intent.getType());
4068 // And we are resetting to find the next component...
4069 intent.setComponent(null);
4070
4071 ActivityInfo aInfo = null;
4072 try {
4073 List<ResolveInfo> resolves =
4074 ActivityThread.getPackageManager().queryIntentActivities(
4075 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004076 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077
4078 // Look for the original activity in the list...
4079 final int N = resolves != null ? resolves.size() : 0;
4080 for (int i=0; i<N; i++) {
4081 ResolveInfo rInfo = resolves.get(i);
4082 if (rInfo.activityInfo.packageName.equals(r.packageName)
4083 && rInfo.activityInfo.name.equals(r.info.name)) {
4084 // We found the current one... the next matching is
4085 // after it.
4086 i++;
4087 if (i<N) {
4088 aInfo = resolves.get(i).activityInfo;
4089 }
4090 break;
4091 }
4092 }
4093 } catch (RemoteException e) {
4094 }
4095
4096 if (aInfo == null) {
4097 // Nobody who is next!
4098 return false;
4099 }
4100
4101 intent.setComponent(new ComponentName(
4102 aInfo.applicationInfo.packageName, aInfo.name));
4103 intent.setFlags(intent.getFlags()&~(
4104 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
4105 Intent.FLAG_ACTIVITY_CLEAR_TOP|
4106 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
4107 Intent.FLAG_ACTIVITY_NEW_TASK));
4108
4109 // Okay now we need to start the new activity, replacing the
4110 // currently running activity. This is a little tricky because
4111 // we want to start the new one as if the current one is finished,
4112 // but not finish the current one first so that there is no flicker.
4113 // And thus...
4114 final boolean wasFinishing = r.finishing;
4115 r.finishing = true;
4116
4117 // Propagate reply information over to the new activity.
4118 final HistoryRecord resultTo = r.resultTo;
4119 final String resultWho = r.resultWho;
4120 final int requestCode = r.requestCode;
4121 r.resultTo = null;
4122 if (resultTo != null) {
4123 resultTo.removeResultsLocked(r, resultWho, requestCode);
4124 }
4125
4126 final long origId = Binder.clearCallingIdentity();
4127 // XXX we are not dealing with propagating grantedUriPermissions...
4128 // those are not yet exposed to user code, so there is no need.
4129 int res = startActivityLocked(r.app.thread, intent,
4130 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004131 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 Binder.restoreCallingIdentity(origId);
4133
4134 r.finishing = wasFinishing;
4135 if (res != START_SUCCESS) {
4136 return false;
4137 }
4138 return true;
4139 }
4140 }
4141
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004142 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004143 Intent intent, String resolvedType, IBinder resultTo,
4144 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004145
4146 // This is so super not safe, that only the system (or okay root)
4147 // can do it.
4148 final int callingUid = Binder.getCallingUid();
4149 if (callingUid != 0 && callingUid != Process.myUid()) {
4150 throw new SecurityException(
4151 "startActivityInPackage only available to the system");
4152 }
4153
The Android Open Source Project4df24232009-03-05 14:34:35 -08004154 final boolean componentSpecified = intent.getComponent() != null;
4155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004156 // Don't modify the client's object!
4157 intent = new Intent(intent);
4158
4159 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004160 ActivityInfo aInfo;
4161 try {
4162 ResolveInfo rInfo =
4163 ActivityThread.getPackageManager().resolveIntent(
4164 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004165 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 aInfo = rInfo != null ? rInfo.activityInfo : null;
4167 } catch (RemoteException e) {
4168 aInfo = null;
4169 }
4170
4171 if (aInfo != null) {
4172 // Store the found target back into the intent, because now that
4173 // we have it we never want to do this again. For example, if the
4174 // user navigates back to this point in the history, we should
4175 // always restart the exact same activity.
4176 intent.setComponent(new ComponentName(
4177 aInfo.applicationInfo.packageName, aInfo.name));
4178 }
4179
4180 synchronized(this) {
4181 return startActivityLocked(null, intent, resolvedType,
4182 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004183 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004184 }
4185 }
4186
Josh Bartel7f208742010-02-25 11:01:44 -06004187 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004188 // Remove any existing entries that are the same kind of task.
4189 int N = mRecentTasks.size();
4190 for (int i=0; i<N; i++) {
4191 TaskRecord tr = mRecentTasks.get(i);
4192 if ((task.affinity != null && task.affinity.equals(tr.affinity))
4193 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
4194 mRecentTasks.remove(i);
4195 i--;
4196 N--;
4197 if (task.intent == null) {
4198 // If the new recent task we are adding is not fully
4199 // specified, then replace it with the existing recent task.
4200 task = tr;
4201 }
4202 }
4203 }
4204 if (N >= MAX_RECENT_TASKS) {
4205 mRecentTasks.remove(N-1);
4206 }
4207 mRecentTasks.add(0, task);
4208 }
4209
4210 public void setRequestedOrientation(IBinder token,
4211 int requestedOrientation) {
4212 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004213 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004214 if (index < 0) {
4215 return;
4216 }
4217 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4218 final long origId = Binder.clearCallingIdentity();
4219 mWindowManager.setAppOrientation(r, requestedOrientation);
4220 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07004221 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004222 r.mayFreezeScreenLocked(r.app) ? r : null);
4223 if (config != null) {
4224 r.frozenBeforeDestroy = true;
4225 if (!updateConfigurationLocked(config, r)) {
4226 resumeTopActivityLocked(null);
4227 }
4228 }
4229 Binder.restoreCallingIdentity(origId);
4230 }
4231 }
4232
4233 public int getRequestedOrientation(IBinder token) {
4234 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004235 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236 if (index < 0) {
4237 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
4238 }
4239 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4240 return mWindowManager.getAppOrientation(r);
4241 }
4242 }
4243
4244 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004245 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004246 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4247 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
4248 if (!r.finishing) {
4249 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
4250 "no-history");
4251 }
4252 } else if (r.app != null && r.app.thread != null) {
4253 if (mFocusedActivity == r) {
4254 setFocusedActivityLocked(topRunningActivityLocked(null));
4255 }
4256 r.resumeKeyDispatchingLocked();
4257 try {
4258 r.stopped = false;
4259 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004260 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004261 TAG, "Stopping visible=" + r.visible + " for " + r);
4262 if (!r.visible) {
4263 mWindowManager.setAppVisibility(r, false);
4264 }
4265 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4266 } catch (Exception e) {
4267 // Maybe just ignore exceptions here... if the process
4268 // has crashed, our death notification will clean things
4269 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004270 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004271 // Just in case, assume it to be stopped.
4272 r.stopped = true;
4273 r.state = ActivityState.STOPPED;
4274 if (r.configDestroy) {
4275 destroyActivityLocked(r, true);
4276 }
4277 }
4278 }
4279 }
4280
4281 /**
4282 * @return Returns true if the activity is being finished, false if for
4283 * some reason it is being left as-is.
4284 */
4285 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4286 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004287 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004288 TAG, "Finishing activity: token=" + token
4289 + ", result=" + resultCode + ", data=" + resultData);
4290
Dianne Hackborn75b03852009-06-12 15:43:26 -07004291 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 if (index < 0) {
4293 return false;
4294 }
4295 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4296
4297 // Is this the last activity left?
4298 boolean lastActivity = true;
4299 for (int i=mHistory.size()-1; i>=0; i--) {
4300 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4301 if (!p.finishing && p != r) {
4302 lastActivity = false;
4303 break;
4304 }
4305 }
4306
4307 // If this is the last activity, but it is the home activity, then
4308 // just don't finish it.
4309 if (lastActivity) {
4310 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4311 return false;
4312 }
4313 }
4314
4315 finishActivityLocked(r, index, resultCode, resultData, reason);
4316 return true;
4317 }
4318
4319 /**
4320 * @return Returns true if this activity has been removed from the history
4321 * list, or false if it is still in the list and will be removed later.
4322 */
4323 private final boolean finishActivityLocked(HistoryRecord r, int index,
4324 int resultCode, Intent resultData, String reason) {
4325 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004326 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004327 return false;
4328 }
4329
4330 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004331 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004332 System.identityHashCode(r),
4333 r.task.taskId, r.shortComponentName, reason);
4334 r.task.numActivities--;
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004335 if (index < (mHistory.size()-1)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004336 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4337 if (next.task == r.task) {
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004338 if (r.frontOfTask) {
4339 // The next activity is now the front of the task.
4340 next.frontOfTask = true;
4341 }
4342 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4343 // If the caller asked that this activity (and all above it)
4344 // be cleared when the task is reset, don't lose that information,
4345 // but propagate it up to the next activity.
4346 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 }
4349 }
4350
4351 r.pauseKeyDispatchingLocked();
4352 if (mFocusedActivity == r) {
4353 setFocusedActivityLocked(topRunningActivityLocked(null));
4354 }
4355
4356 // send the result
4357 HistoryRecord resultTo = r.resultTo;
4358 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004359 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004360 + " who=" + r.resultWho + " req=" + r.requestCode
4361 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004362 if (r.info.applicationInfo.uid > 0) {
4363 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4364 r.packageName, resultData, r);
4365 }
4366 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4367 resultData);
4368 r.resultTo = null;
4369 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004370 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004371
4372 // Make sure this HistoryRecord is not holding on to other resources,
4373 // because clients have remote IPC references to this object so we
4374 // can't assume that will go away and want to avoid circular IPC refs.
4375 r.results = null;
4376 r.pendingResults = null;
4377 r.newIntents = null;
4378 r.icicle = null;
4379
4380 if (mPendingThumbnails.size() > 0) {
4381 // There are clients waiting to receive thumbnails so, in case
4382 // this is an activity that someone is waiting for, add it
4383 // to the pending list so we can correctly update the clients.
4384 mCancelledThumbnails.add(r);
4385 }
4386
4387 if (mResumedActivity == r) {
4388 boolean endTask = index <= 0
4389 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004390 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 "Prepare close transition: finishing " + r);
4392 mWindowManager.prepareAppTransition(endTask
4393 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4394 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4395
4396 // Tell window manager to prepare for this one to be removed.
4397 mWindowManager.setAppVisibility(r, false);
4398
4399 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004400 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4401 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004402 startPausingLocked(false, false);
4403 }
4404
4405 } else if (r.state != ActivityState.PAUSING) {
4406 // If the activity is PAUSING, we will complete the finish once
4407 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004408 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004409 return finishCurrentActivityLocked(r, index,
4410 FINISH_AFTER_PAUSE) == null;
4411 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004412 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 }
4414
4415 return false;
4416 }
4417
4418 private static final int FINISH_IMMEDIATELY = 0;
4419 private static final int FINISH_AFTER_PAUSE = 1;
4420 private static final int FINISH_AFTER_VISIBLE = 2;
4421
4422 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4423 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004424 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004425 if (index < 0) {
4426 return null;
4427 }
4428
4429 return finishCurrentActivityLocked(r, index, mode);
4430 }
4431
4432 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4433 int index, int mode) {
4434 // First things first: if this activity is currently visible,
4435 // and the resumed activity is not yet visible, then hold off on
4436 // finishing until the resumed one becomes visible.
4437 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4438 if (!mStoppingActivities.contains(r)) {
4439 mStoppingActivities.add(r);
4440 if (mStoppingActivities.size() > 3) {
4441 // If we already have a few activities waiting to stop,
4442 // then give up on things going idle and start clearing
4443 // them out.
4444 Message msg = Message.obtain();
4445 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4446 mHandler.sendMessage(msg);
4447 }
4448 }
4449 r.state = ActivityState.STOPPING;
4450 updateOomAdjLocked();
4451 return r;
4452 }
4453
4454 // make sure the record is cleaned out of other places.
4455 mStoppingActivities.remove(r);
4456 mWaitingVisibleActivities.remove(r);
4457 if (mResumedActivity == r) {
4458 mResumedActivity = null;
4459 }
4460 final ActivityState prevState = r.state;
4461 r.state = ActivityState.FINISHING;
4462
4463 if (mode == FINISH_IMMEDIATELY
4464 || prevState == ActivityState.STOPPED
4465 || prevState == ActivityState.INITIALIZING) {
4466 // If this activity is already stopped, we can just finish
4467 // it right now.
4468 return destroyActivityLocked(r, true) ? null : r;
4469 } else {
4470 // Need to go through the full pause cycle to get this
4471 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004472 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 mFinishingActivities.add(r);
4474 resumeTopActivityLocked(null);
4475 }
4476 return r;
4477 }
4478
4479 /**
4480 * This is the internal entry point for handling Activity.finish().
4481 *
4482 * @param token The Binder token referencing the Activity we want to finish.
4483 * @param resultCode Result code, if any, from this Activity.
4484 * @param resultData Result data (Intent), if any, from this Activity.
4485 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004486 * @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 -08004487 */
4488 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4489 // Refuse possible leaked file descriptors
4490 if (resultData != null && resultData.hasFileDescriptors() == true) {
4491 throw new IllegalArgumentException("File descriptors passed in Intent");
4492 }
4493
4494 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004495 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 // Find the first activity that is not finishing.
4497 HistoryRecord next = topRunningActivityLocked(token, 0);
4498 if (next != null) {
4499 // ask watcher if this is allowed
4500 boolean resumeOK = true;
4501 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004502 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004504 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 }
4506
4507 if (!resumeOK) {
4508 return false;
4509 }
4510 }
4511 }
4512 final long origId = Binder.clearCallingIdentity();
4513 boolean res = requestFinishActivityLocked(token, resultCode,
4514 resultData, "app-request");
4515 Binder.restoreCallingIdentity(origId);
4516 return res;
4517 }
4518 }
4519
Dianne Hackborn860755f2010-06-03 18:47:52 -07004520 public final void finishHeavyWeightApp() {
4521 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4522 != PackageManager.PERMISSION_GRANTED) {
4523 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
4524 + Binder.getCallingPid()
4525 + ", uid=" + Binder.getCallingUid()
4526 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4527 Slog.w(TAG, msg);
4528 throw new SecurityException(msg);
4529 }
4530
4531 synchronized(this) {
4532 if (mHeavyWeightProcess == null) {
4533 return;
4534 }
4535
4536 ArrayList<HistoryRecord> activities = new ArrayList<HistoryRecord>(
4537 mHeavyWeightProcess.activities);
4538 for (int i=0; i<activities.size(); i++) {
4539 HistoryRecord r = activities.get(i);
4540 if (!r.finishing) {
4541 int index = indexOfTokenLocked(r);
4542 if (index >= 0) {
4543 finishActivityLocked(r, index, Activity.RESULT_CANCELED,
4544 null, "finish-heavy");
4545 }
4546 }
4547 }
4548
4549 mHeavyWeightProcess = null;
4550 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4551 }
4552 }
4553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4555 String resultWho, int requestCode, int resultCode, Intent data) {
4556
4557 if (callingUid > 0) {
4558 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4559 data, r);
4560 }
4561
Joe Onorato8a9b2202010-02-26 18:56:32 -08004562 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004563 + " : who=" + resultWho + " req=" + requestCode
4564 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4566 try {
4567 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4568 list.add(new ResultInfo(resultWho, requestCode,
4569 resultCode, data));
4570 r.app.thread.scheduleSendResult(r, list);
4571 return;
4572 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004573 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004574 }
4575 }
4576
4577 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4578 }
4579
4580 public final void finishSubActivity(IBinder token, String resultWho,
4581 int requestCode) {
4582 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004583 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004584 if (index < 0) {
4585 return;
4586 }
4587 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4588
4589 final long origId = Binder.clearCallingIdentity();
4590
4591 int i;
4592 for (i=mHistory.size()-1; i>=0; i--) {
4593 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4594 if (r.resultTo == self && r.requestCode == requestCode) {
4595 if ((r.resultWho == null && resultWho == null) ||
4596 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4597 finishActivityLocked(r, i,
4598 Activity.RESULT_CANCELED, null, "request-sub");
4599 }
4600 }
4601 }
4602
4603 Binder.restoreCallingIdentity(origId);
4604 }
4605 }
4606
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004607 public boolean willActivityBeVisible(IBinder token) {
4608 synchronized(this) {
4609 int i;
4610 for (i=mHistory.size()-1; i>=0; i--) {
4611 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4612 if (r == token) {
4613 return true;
4614 }
4615 if (r.fullscreen && !r.finishing) {
4616 return false;
4617 }
4618 }
4619 return true;
4620 }
4621 }
4622
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004623 public void overridePendingTransition(IBinder token, String packageName,
4624 int enterAnim, int exitAnim) {
4625 synchronized(this) {
4626 int index = indexOfTokenLocked(token);
4627 if (index < 0) {
4628 return;
4629 }
4630 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4631
4632 final long origId = Binder.clearCallingIdentity();
4633
4634 if (self.state == ActivityState.RESUMED
4635 || self.state == ActivityState.PAUSING) {
4636 mWindowManager.overridePendingAppTransition(packageName,
4637 enterAnim, exitAnim);
4638 }
4639
4640 Binder.restoreCallingIdentity(origId);
4641 }
4642 }
4643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644 /**
4645 * Perform clean-up of service connections in an activity record.
4646 */
4647 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4648 // Throw away any services that have been bound by this activity.
4649 if (r.connections != null) {
4650 Iterator<ConnectionRecord> it = r.connections.iterator();
4651 while (it.hasNext()) {
4652 ConnectionRecord c = it.next();
4653 removeConnectionLocked(c, null, r);
4654 }
4655 r.connections = null;
4656 }
4657 }
4658
4659 /**
4660 * Perform the common clean-up of an activity record. This is called both
4661 * as part of destroyActivityLocked() (when destroying the client-side
4662 * representation) and cleaning things up as a result of its hosting
4663 * processing going away, in which case there is no remaining client-side
4664 * state to destroy so only the cleanup here is needed.
4665 */
4666 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4667 if (mResumedActivity == r) {
4668 mResumedActivity = null;
4669 }
4670 if (mFocusedActivity == r) {
4671 mFocusedActivity = null;
4672 }
4673
4674 r.configDestroy = false;
4675 r.frozenBeforeDestroy = false;
4676
4677 // Make sure this record is no longer in the pending finishes list.
4678 // This could happen, for example, if we are trimming activities
4679 // down to the max limit while they are still waiting to finish.
4680 mFinishingActivities.remove(r);
4681 mWaitingVisibleActivities.remove(r);
4682
4683 // Remove any pending results.
4684 if (r.finishing && r.pendingResults != null) {
4685 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4686 PendingIntentRecord rec = apr.get();
4687 if (rec != null) {
4688 cancelIntentSenderLocked(rec, false);
4689 }
4690 }
4691 r.pendingResults = null;
4692 }
4693
4694 if (cleanServices) {
4695 cleanUpActivityServicesLocked(r);
4696 }
4697
4698 if (mPendingThumbnails.size() > 0) {
4699 // There are clients waiting to receive thumbnails so, in case
4700 // this is an activity that someone is waiting for, add it
4701 // to the pending list so we can correctly update the clients.
4702 mCancelledThumbnails.add(r);
4703 }
4704
4705 // Get rid of any pending idle timeouts.
4706 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4707 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4708 }
4709
4710 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4711 if (r.state != ActivityState.DESTROYED) {
4712 mHistory.remove(r);
4713 r.inHistory = false;
4714 r.state = ActivityState.DESTROYED;
4715 mWindowManager.removeAppToken(r);
4716 if (VALIDATE_TOKENS) {
4717 mWindowManager.validateAppTokens(mHistory);
4718 }
4719 cleanUpActivityServicesLocked(r);
4720 removeActivityUriPermissionsLocked(r);
4721 }
4722 }
4723
4724 /**
4725 * Destroy the current CLIENT SIDE instance of an activity. This may be
4726 * called both when actually finishing an activity, or when performing
4727 * a configuration switch where we destroy the current client-side object
4728 * but then create a new client-side object for this same HistoryRecord.
4729 */
4730 private final boolean destroyActivityLocked(HistoryRecord r,
4731 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004732 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004733 TAG, "Removing activity: token=" + r
4734 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004735 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004736 System.identityHashCode(r),
4737 r.task.taskId, r.shortComponentName);
4738
4739 boolean removedFromHistory = false;
4740
4741 cleanUpActivityLocked(r, false);
4742
Dianne Hackborn03abb812010-01-04 18:43:19 -08004743 final boolean hadApp = r.app != null;
4744
4745 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 if (removeFromApp) {
4747 int idx = r.app.activities.indexOf(r);
4748 if (idx >= 0) {
4749 r.app.activities.remove(idx);
4750 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004751 if (mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4752 mHeavyWeightProcess = null;
4753 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004755 if (r.persistent) {
4756 decPersistentCountLocked(r.app);
4757 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004758 if (r.app.activities.size() == 0) {
4759 // No longer have activities, so update location in
4760 // LRU list.
4761 updateLruProcessLocked(r.app, true, false);
4762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763 }
4764
4765 boolean skipDestroy = false;
4766
4767 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004768 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004769 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4770 r.configChangeFlags);
4771 } catch (Exception e) {
4772 // We can just ignore exceptions here... if the process
4773 // has crashed, our death notification will clean things
4774 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004775 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004776 if (r.finishing) {
4777 removeActivityFromHistoryLocked(r);
4778 removedFromHistory = true;
4779 skipDestroy = true;
4780 }
4781 }
4782
4783 r.app = null;
4784 r.nowVisible = false;
4785
4786 if (r.finishing && !skipDestroy) {
4787 r.state = ActivityState.DESTROYING;
4788 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4789 msg.obj = r;
4790 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4791 } else {
4792 r.state = ActivityState.DESTROYED;
4793 }
4794 } else {
4795 // remove this record from the history.
4796 if (r.finishing) {
4797 removeActivityFromHistoryLocked(r);
4798 removedFromHistory = true;
4799 } else {
4800 r.state = ActivityState.DESTROYED;
4801 }
4802 }
4803
4804 r.configChangeFlags = 0;
4805
Dianne Hackborn03abb812010-01-04 18:43:19 -08004806 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004807 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004808 }
4809
4810 return removedFromHistory;
4811 }
4812
Dianne Hackborn03abb812010-01-04 18:43:19 -08004813 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004814 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004815 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816 TAG, "Removing app " + app + " from list " + list
4817 + " with " + i + " entries");
4818 while (i > 0) {
4819 i--;
4820 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004821 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004822 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4823 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004824 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004825 list.remove(i);
4826 }
4827 }
4828 }
4829
4830 /**
4831 * Main function for removing an existing process from the activity manager
4832 * as a result of that process going away. Clears out all connections
4833 * to the process.
4834 */
4835 private final void handleAppDiedLocked(ProcessRecord app,
4836 boolean restarting) {
4837 cleanUpApplicationRecordLocked(app, restarting, -1);
4838 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004839 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 }
4841
4842 // Just in case...
4843 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004844 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 mPausingActivity = null;
4846 }
4847 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4848 mLastPausedActivity = null;
4849 }
4850
4851 // Remove this application's activities from active lists.
4852 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4853 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4854 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4855 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4856
4857 boolean atTop = true;
4858 boolean hasVisibleActivities = false;
4859
4860 // Clean out the history list.
4861 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004862 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 TAG, "Removing app " + app + " from history with " + i + " entries");
4864 while (i > 0) {
4865 i--;
4866 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004867 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4869 if (r.app == app) {
4870 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004871 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004872 TAG, "Removing this entry! frozen=" + r.haveState
4873 + " finishing=" + r.finishing);
4874 mHistory.remove(i);
4875
4876 r.inHistory = false;
4877 mWindowManager.removeAppToken(r);
4878 if (VALIDATE_TOKENS) {
4879 mWindowManager.validateAppTokens(mHistory);
4880 }
4881 removeActivityUriPermissionsLocked(r);
4882
4883 } else {
4884 // We have the current state for this activity, so
4885 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004886 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004887 TAG, "Keeping entry, setting app to null");
4888 if (r.visible) {
4889 hasVisibleActivities = true;
4890 }
4891 r.app = null;
4892 r.nowVisible = false;
4893 if (!r.haveState) {
4894 r.icicle = null;
4895 }
4896 }
4897
4898 cleanUpActivityLocked(r, true);
4899 r.state = ActivityState.STOPPED;
4900 }
4901 atTop = false;
4902 }
4903
4904 app.activities.clear();
4905
4906 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004907 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 + " running instrumentation " + app.instrumentationClass);
4909 Bundle info = new Bundle();
4910 info.putString("shortMsg", "Process crashed.");
4911 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4912 }
4913
4914 if (!restarting) {
4915 if (!resumeTopActivityLocked(null)) {
4916 // If there was nothing to resume, and we are not already
4917 // restarting this process, but there is a visible activity that
4918 // is hosted by the process... then make sure all visible
4919 // activities are running, taking care of restarting this
4920 // process.
4921 if (hasVisibleActivities) {
4922 ensureActivitiesVisibleLocked(null, 0);
4923 }
4924 }
4925 }
4926 }
4927
4928 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4929 IBinder threadBinder = thread.asBinder();
4930
4931 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004932 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4933 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004934 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4935 return i;
4936 }
4937 }
4938 return -1;
4939 }
4940
4941 private final ProcessRecord getRecordForAppLocked(
4942 IApplicationThread thread) {
4943 if (thread == null) {
4944 return null;
4945 }
4946
4947 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004948 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949 }
4950
4951 private final void appDiedLocked(ProcessRecord app, int pid,
4952 IApplicationThread thread) {
4953
4954 mProcDeaths[0]++;
4955
Magnus Edlund7bb25812010-02-24 15:45:06 +01004956 // Clean up already done if the process has been re-started.
4957 if (app.pid == pid && app.thread != null &&
4958 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07004959 if (!app.killedBackground) {
4960 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
4961 + ") has died.");
4962 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08004963 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004964 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965 TAG, "Dying app: " + app + ", pid: " + pid
4966 + ", thread: " + thread.asBinder());
4967 boolean doLowMem = app.instrumentationClass == null;
4968 handleAppDiedLocked(app, false);
4969
4970 if (doLowMem) {
4971 // If there are no longer any background processes running,
4972 // and the app that died was not running instrumentation,
4973 // then tell everyone we are now low on memory.
4974 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004975 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4976 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4978 haveBg = true;
4979 break;
4980 }
4981 }
4982
4983 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004984 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004985 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004986 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004987 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4988 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004989 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004990 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4991 // The low memory report is overriding any current
4992 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07004993 // heavy/important/visible/foreground processes first.
4994 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004995 rec.lastRequestedGc = 0;
4996 } else {
4997 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004998 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004999 rec.reportLowMemory = true;
5000 rec.lastLowMemory = now;
5001 mProcessesToGc.remove(rec);
5002 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005003 }
5004 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005005 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005006 }
5007 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01005008 } else if (app.pid != pid) {
5009 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005010 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01005011 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08005012 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005013 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005014 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005015 + thread.asBinder());
5016 }
5017 }
5018
Dan Egnor42471dd2010-01-07 17:25:22 -08005019 /**
5020 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07005021 * @param clearTraces causes the dump file to be erased prior to the new
5022 * traces being written, if true; when false, the new traces will be
5023 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08005024 * @param pids of dalvik VM processes to dump stack traces for
5025 * @return file containing stack traces, or null if no dump file is configured
5026 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07005027 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005028 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
5029 if (tracesPath == null || tracesPath.length() == 0) {
5030 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005031 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005032
5033 File tracesFile = new File(tracesPath);
5034 try {
5035 File tracesDir = tracesFile.getParentFile();
5036 if (!tracesDir.exists()) tracesFile.mkdirs();
5037 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
5038
Christopher Tate6ee412d2010-05-28 12:01:56 -07005039 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08005040 tracesFile.createNewFile();
5041 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
5042 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005043 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005044 return null;
5045 }
5046
5047 // Use a FileObserver to detect when traces finish writing.
5048 // The order of traces is considered important to maintain for legibility.
5049 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
5050 public synchronized void onEvent(int event, String path) { notify(); }
5051 };
5052
5053 try {
5054 observer.startWatching();
5055 int num = pids.size();
5056 for (int i = 0; i < num; i++) {
5057 synchronized (observer) {
5058 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
5059 observer.wait(200); // Wait for write-close, give up after 200msec
5060 }
5061 }
5062 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08005063 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005064 } finally {
5065 observer.stopWatching();
5066 }
5067
5068 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005069 }
5070
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005071 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08005072 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005073 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005074
5075 synchronized (this) {
5076 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
5077 if (mShuttingDown) {
5078 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
5079 return;
5080 } else if (app.notResponding) {
5081 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
5082 return;
5083 } else if (app.crashing) {
5084 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
5085 return;
5086 }
5087
5088 // In case we come through here for the same app before completing
5089 // this one, mark as anring now so we will bail out.
5090 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08005091
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005092 // Log the ANR to the event log.
5093 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
5094 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08005095
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005096 // Dump thread traces as quickly as we can, starting with "interesting" processes.
5097 pids.add(app.pid);
5098
5099 int parentPid = app.pid;
5100 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
5101 if (parentPid != app.pid) pids.add(parentPid);
5102
5103 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08005104
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005105 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
5106 ProcessRecord r = mLruProcesses.get(i);
5107 if (r != null && r.thread != null) {
5108 int pid = r.pid;
5109 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
5110 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005111 }
5112 }
5113
Christopher Tate6ee412d2010-05-28 12:01:56 -07005114 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08005115
5116 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005117 StringBuilder info = mStringBuilder;
5118 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08005119 info.append("ANR in ").append(app.processName);
5120 if (activity != null && activity.shortComponentName != null) {
5121 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07005122 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08005123 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005124 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005125 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005126 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005127 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005128 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130
Dan Egnor42471dd2010-01-07 17:25:22 -08005131 String cpuInfo = null;
5132 if (MONITOR_CPU_USAGE) {
5133 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005134 synchronized (mProcessStatsThread) {
5135 cpuInfo = mProcessStats.printCurrentState();
5136 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005137 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 }
5139
Joe Onorato8a9b2202010-02-26 18:56:32 -08005140 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08005141 if (tracesFile == null) {
5142 // There is no trace file, so dump (only) the alleged culprit's threads to the log
5143 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
5144 }
5145
5146 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
5147
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005148 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08005150 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
5151 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005152 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005153 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
5154 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005155 }
5156 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005157 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005158 }
5159 }
5160
Dan Egnor42471dd2010-01-07 17:25:22 -08005161 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
5162 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
5163 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005164
5165 synchronized (this) {
5166 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
5167 Process.killProcess(app.pid);
5168 return;
5169 }
5170
5171 // Set the app's notResponding state, and look up the errorReportReceiver
5172 makeAppNotRespondingLocked(app,
5173 activity != null ? activity.shortComponentName : null,
5174 annotation != null ? "ANR " + annotation : "ANR",
5175 info.toString());
5176
5177 // Bring up the infamous App Not Responding dialog
5178 Message msg = Message.obtain();
5179 HashMap map = new HashMap();
5180 msg.what = SHOW_NOT_RESPONDING_MSG;
5181 msg.obj = map;
5182 map.put("app", app);
5183 if (activity != null) {
5184 map.put("activity", activity);
5185 }
5186
5187 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08005188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005189 }
5190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 private final void decPersistentCountLocked(ProcessRecord app)
5192 {
5193 app.persistentActivities--;
5194 if (app.persistentActivities > 0) {
5195 // Still more of 'em...
5196 return;
5197 }
5198 if (app.persistent) {
5199 // Ah, but the application itself is persistent. Whatever!
5200 return;
5201 }
5202
5203 // App is no longer persistent... make sure it and the ones
5204 // following it in the LRU list have the correc oom_adj.
5205 updateOomAdjLocked();
5206 }
5207
5208 public void setPersistent(IBinder token, boolean isPersistent) {
5209 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
5210 != PackageManager.PERMISSION_GRANTED) {
5211 String msg = "Permission Denial: setPersistent() from pid="
5212 + Binder.getCallingPid()
5213 + ", uid=" + Binder.getCallingUid()
5214 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005215 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005216 throw new SecurityException(msg);
5217 }
5218
5219 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005220 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005221 if (index < 0) {
5222 return;
5223 }
5224 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5225 ProcessRecord app = r.app;
5226
Joe Onorato8a9b2202010-02-26 18:56:32 -08005227 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 TAG, "Setting persistence " + isPersistent + ": " + r);
5229
5230 if (isPersistent) {
5231 if (r.persistent) {
5232 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005233 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005234 return;
5235 }
5236 r.persistent = true;
5237 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005238 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005239 if (app.persistentActivities > 1) {
5240 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005241 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005242 return;
5243 }
5244 if (app.persistent) {
5245 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005246 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005247 return;
5248 }
5249
5250 // App is now persistent... make sure it and the ones
5251 // following it now have the correct oom_adj.
5252 final long origId = Binder.clearCallingIdentity();
5253 updateOomAdjLocked();
5254 Binder.restoreCallingIdentity(origId);
5255
5256 } else {
5257 if (!r.persistent) {
5258 // Okay okay, I heard you already!
5259 return;
5260 }
5261 r.persistent = false;
5262 final long origId = Binder.clearCallingIdentity();
5263 decPersistentCountLocked(app);
5264 Binder.restoreCallingIdentity(origId);
5265
5266 }
5267 }
5268 }
5269
5270 public boolean clearApplicationUserData(final String packageName,
5271 final IPackageDataObserver observer) {
5272 int uid = Binder.getCallingUid();
5273 int pid = Binder.getCallingPid();
5274 long callingId = Binder.clearCallingIdentity();
5275 try {
5276 IPackageManager pm = ActivityThread.getPackageManager();
5277 int pkgUid = -1;
5278 synchronized(this) {
5279 try {
5280 pkgUid = pm.getPackageUid(packageName);
5281 } catch (RemoteException e) {
5282 }
5283 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005284 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005285 return false;
5286 }
5287 if (uid == pkgUid || checkComponentPermission(
5288 android.Manifest.permission.CLEAR_APP_USER_DATA,
5289 pid, uid, -1)
5290 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005291 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005292 } else {
5293 throw new SecurityException(pid+" does not have permission:"+
5294 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5295 "for process:"+packageName);
5296 }
5297 }
5298
5299 try {
5300 //clear application user data
5301 pm.clearApplicationUserData(packageName, observer);
5302 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5303 Uri.fromParts("package", packageName, null));
5304 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005305 synchronized (this) {
5306 broadcastIntentLocked(null, null, intent,
5307 null, null, 0, null, null, null,
5308 false, false, MY_PID, Process.SYSTEM_UID);
5309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 } catch (RemoteException e) {
5311 }
5312 } finally {
5313 Binder.restoreCallingIdentity(callingId);
5314 }
5315 return true;
5316 }
5317
Dianne Hackborn03abb812010-01-04 18:43:19 -08005318 public void killBackgroundProcesses(final String packageName) {
5319 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5320 != PackageManager.PERMISSION_GRANTED &&
5321 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5322 != PackageManager.PERMISSION_GRANTED) {
5323 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 + Binder.getCallingPid()
5325 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005326 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005327 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005328 throw new SecurityException(msg);
5329 }
5330
5331 long callingId = Binder.clearCallingIdentity();
5332 try {
5333 IPackageManager pm = ActivityThread.getPackageManager();
5334 int pkgUid = -1;
5335 synchronized(this) {
5336 try {
5337 pkgUid = pm.getPackageUid(packageName);
5338 } catch (RemoteException e) {
5339 }
5340 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005341 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 return;
5343 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005344 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005345 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005346 }
5347 } finally {
5348 Binder.restoreCallingIdentity(callingId);
5349 }
5350 }
5351
5352 public void forceStopPackage(final String packageName) {
5353 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5354 != PackageManager.PERMISSION_GRANTED) {
5355 String msg = "Permission Denial: forceStopPackage() from pid="
5356 + Binder.getCallingPid()
5357 + ", uid=" + Binder.getCallingUid()
5358 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005359 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005360 throw new SecurityException(msg);
5361 }
5362
5363 long callingId = Binder.clearCallingIdentity();
5364 try {
5365 IPackageManager pm = ActivityThread.getPackageManager();
5366 int pkgUid = -1;
5367 synchronized(this) {
5368 try {
5369 pkgUid = pm.getPackageUid(packageName);
5370 } catch (RemoteException e) {
5371 }
5372 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005373 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005374 return;
5375 }
5376 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005377 }
5378 } finally {
5379 Binder.restoreCallingIdentity(callingId);
5380 }
5381 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005382
5383 /*
5384 * The pkg name and uid have to be specified.
5385 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5386 */
5387 public void killApplicationWithUid(String pkg, int uid) {
5388 if (pkg == null) {
5389 return;
5390 }
5391 // Make sure the uid is valid.
5392 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005393 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005394 return;
5395 }
5396 int callerUid = Binder.getCallingUid();
5397 // Only the system server can kill an application
5398 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005399 // Post an aysnc message to kill the application
5400 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5401 msg.arg1 = uid;
5402 msg.arg2 = 0;
5403 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005404 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005405 } else {
5406 throw new SecurityException(callerUid + " cannot kill pkg: " +
5407 pkg);
5408 }
5409 }
5410
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005411 public void closeSystemDialogs(String reason) {
5412 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5413 if (reason != null) {
5414 intent.putExtra("reason", reason);
5415 }
5416
5417 final int uid = Binder.getCallingUid();
5418 final long origId = Binder.clearCallingIdentity();
5419 synchronized (this) {
5420 int i = mWatchers.beginBroadcast();
5421 while (i > 0) {
5422 i--;
5423 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5424 if (w != null) {
5425 try {
5426 w.closingSystemDialogs(reason);
5427 } catch (RemoteException e) {
5428 }
5429 }
5430 }
5431 mWatchers.finishBroadcast();
5432
Dianne Hackbornffa42482009-09-23 22:20:11 -07005433 mWindowManager.closeSystemDialogs(reason);
5434
5435 for (i=mHistory.size()-1; i>=0; i--) {
5436 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5437 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5438 finishActivityLocked(r, i,
5439 Activity.RESULT_CANCELED, null, "close-sys");
5440 }
5441 }
5442
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005443 broadcastIntentLocked(null, null, intent, null,
5444 null, 0, null, null, null, false, false, -1, uid);
5445 }
5446 Binder.restoreCallingIdentity(origId);
5447 }
5448
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005449 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005450 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005451 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5452 for (int i=pids.length-1; i>=0; i--) {
5453 infos[i] = new Debug.MemoryInfo();
5454 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005455 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005456 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005457 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005458
5459 public void killApplicationProcess(String processName, int uid) {
5460 if (processName == null) {
5461 return;
5462 }
5463
5464 int callerUid = Binder.getCallingUid();
5465 // Only the system server can kill an application
5466 if (callerUid == Process.SYSTEM_UID) {
5467 synchronized (this) {
5468 ProcessRecord app = getProcessRecordLocked(processName, uid);
5469 if (app != null) {
5470 try {
5471 app.thread.scheduleSuicide();
5472 } catch (RemoteException e) {
5473 // If the other end already died, then our work here is done.
5474 }
5475 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005476 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005477 + processName + " / " + uid);
5478 }
5479 }
5480 } else {
5481 throw new SecurityException(callerUid + " cannot kill app process: " +
5482 processName);
5483 }
5484 }
5485
Dianne Hackborn03abb812010-01-04 18:43:19 -08005486 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005487 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5489 Uri.fromParts("package", packageName, null));
5490 intent.putExtra(Intent.EXTRA_UID, uid);
5491 broadcastIntentLocked(null, null, intent,
5492 null, null, 0, null, null, null,
5493 false, false, MY_PID, Process.SYSTEM_UID);
5494 }
5495
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005496 private final boolean killPackageProcessesLocked(String packageName, int uid,
5497 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005498 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499
Dianne Hackborn03abb812010-01-04 18:43:19 -08005500 // Remove all processes this package may have touched: all with the
5501 // same UID (except for the system or root user), and all whose name
5502 // matches the package name.
5503 final String procNamePrefix = packageName + ":";
5504 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5505 final int NA = apps.size();
5506 for (int ia=0; ia<NA; ia++) {
5507 ProcessRecord app = apps.valueAt(ia);
5508 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005509 if (doit) {
5510 procs.add(app);
5511 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005512 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5513 || app.processName.equals(packageName)
5514 || app.processName.startsWith(procNamePrefix)) {
5515 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005516 if (!doit) {
5517 return true;
5518 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005519 app.removed = true;
5520 procs.add(app);
5521 }
5522 }
5523 }
5524 }
5525
5526 int N = procs.size();
5527 for (int i=0; i<N; i++) {
5528 removeProcessLocked(procs.get(i), callerWillRestart);
5529 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005530 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005531 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005532
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005533 private final boolean forceStopPackageLocked(String name, int uid,
5534 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005535 int i, N;
5536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005537 if (uid < 0) {
5538 try {
5539 uid = ActivityThread.getPackageManager().getPackageUid(name);
5540 } catch (RemoteException e) {
5541 }
5542 }
5543
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005544 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005545 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005546
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005547 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5548 while (badApps.hasNext()) {
5549 SparseArray<Long> ba = badApps.next();
5550 if (ba.get(uid) != null) {
5551 badApps.remove();
5552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005553 }
5554 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005555
5556 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5557 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558
5559 for (i=mHistory.size()-1; i>=0; i--) {
5560 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5561 if (r.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 finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 if (r.app != null) {
5568 r.app.removed = true;
5569 }
5570 r.app = null;
5571 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5572 }
5573 }
5574
5575 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5576 for (ServiceRecord service : mServices.values()) {
5577 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005578 if (!doit) {
5579 return true;
5580 }
5581 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005582 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005583 if (service.app != null) {
5584 service.app.removed = true;
5585 }
5586 service.app = null;
5587 services.add(service);
5588 }
5589 }
5590
5591 N = services.size();
5592 for (i=0; i<N; i++) {
5593 bringDownServiceLocked(services.get(i), true);
5594 }
5595
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005596 if (doit) {
5597 if (purgeCache) {
5598 AttributeCache ac = AttributeCache.instance();
5599 if (ac != null) {
5600 ac.removePackage(name);
5601 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005602 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005603 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005604 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005605
5606 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005607 }
5608
5609 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5610 final String name = app.processName;
5611 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005612 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 TAG, "Force removing process " + app + " (" + name
5614 + "/" + uid + ")");
5615
5616 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005617 if (mHeavyWeightProcess == app) {
5618 mHeavyWeightProcess = null;
5619 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005621 boolean needRestart = false;
5622 if (app.pid > 0 && app.pid != MY_PID) {
5623 int pid = app.pid;
5624 synchronized (mPidsSelfLocked) {
5625 mPidsSelfLocked.remove(pid);
5626 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5627 }
5628 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005629 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005630 Process.killProcess(pid);
5631
5632 if (app.persistent) {
5633 if (!callerWillRestart) {
5634 addAppLocked(app.info);
5635 } else {
5636 needRestart = true;
5637 }
5638 }
5639 } else {
5640 mRemovedProcesses.add(app);
5641 }
5642
5643 return needRestart;
5644 }
5645
5646 private final void processStartTimedOutLocked(ProcessRecord app) {
5647 final int pid = app.pid;
5648 boolean gone = false;
5649 synchronized (mPidsSelfLocked) {
5650 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5651 if (knownApp != null && knownApp.thread == null) {
5652 mPidsSelfLocked.remove(pid);
5653 gone = true;
5654 }
5655 }
5656
5657 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005658 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005659 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005660 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005661 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005662 if (mHeavyWeightProcess == app) {
5663 mHeavyWeightProcess = null;
5664 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5665 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005666 // Take care of any launching providers waiting for this process.
5667 checkAppInLaunchingProvidersLocked(app, true);
5668 // Take care of any services that are waiting for the process.
5669 for (int i=0; i<mPendingServices.size(); i++) {
5670 ServiceRecord sr = mPendingServices.get(i);
5671 if (app.info.uid == sr.appInfo.uid
5672 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005673 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005674 mPendingServices.remove(i);
5675 i--;
5676 bringDownServiceLocked(sr, true);
5677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005679 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005680 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005681 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005682 try {
5683 IBackupManager bm = IBackupManager.Stub.asInterface(
5684 ServiceManager.getService(Context.BACKUP_SERVICE));
5685 bm.agentDisconnected(app.info.packageName);
5686 } catch (RemoteException e) {
5687 // Can't happen; the backup manager is local
5688 }
5689 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005690 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005691 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005692 mPendingBroadcast = null;
5693 scheduleBroadcastsLocked();
5694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005695 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005696 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005697 }
5698 }
5699
5700 private final boolean attachApplicationLocked(IApplicationThread thread,
5701 int pid) {
5702
5703 // Find the application record that is being attached... either via
5704 // the pid if we are running in multiple processes, or just pull the
5705 // next app record if we are emulating process with anonymous threads.
5706 ProcessRecord app;
5707 if (pid != MY_PID && pid >= 0) {
5708 synchronized (mPidsSelfLocked) {
5709 app = mPidsSelfLocked.get(pid);
5710 }
5711 } else if (mStartingProcesses.size() > 0) {
5712 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005713 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 } else {
5715 app = null;
5716 }
5717
5718 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005719 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005721 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005722 if (pid > 0 && pid != MY_PID) {
5723 Process.killProcess(pid);
5724 } else {
5725 try {
5726 thread.scheduleExit();
5727 } catch (Exception e) {
5728 // Ignore exceptions.
5729 }
5730 }
5731 return false;
5732 }
5733
5734 // If this application record is still attached to a previous
5735 // process, clean it up now.
5736 if (app.thread != null) {
5737 handleAppDiedLocked(app, true);
5738 }
5739
5740 // Tell the process all about itself.
5741
Joe Onorato8a9b2202010-02-26 18:56:32 -08005742 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005743 TAG, "Binding process pid " + pid + " to record " + app);
5744
5745 String processName = app.processName;
5746 try {
5747 thread.asBinder().linkToDeath(new AppDeathRecipient(
5748 app, pid, thread), 0);
5749 } catch (RemoteException e) {
5750 app.resetPackageList();
5751 startProcessLocked(app, "link fail", processName);
5752 return false;
5753 }
5754
Doug Zongker2bec3d42009-12-04 12:52:44 -08005755 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005756
5757 app.thread = thread;
5758 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005759 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5760 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005761 app.forcingToForeground = null;
5762 app.foregroundServices = false;
5763 app.debugging = false;
5764
5765 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5766
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005767 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5768 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005769
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005770 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005771 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005772 }
5773
Joe Onorato8a9b2202010-02-26 18:56:32 -08005774 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005775 TAG, "New app record " + app
5776 + " thread=" + thread.asBinder() + " pid=" + pid);
5777 try {
5778 int testMode = IApplicationThread.DEBUG_OFF;
5779 if (mDebugApp != null && mDebugApp.equals(processName)) {
5780 testMode = mWaitForDebugger
5781 ? IApplicationThread.DEBUG_WAIT
5782 : IApplicationThread.DEBUG_ON;
5783 app.debugging = true;
5784 if (mDebugTransient) {
5785 mDebugApp = mOrigDebugApp;
5786 mWaitForDebugger = mOrigWaitForDebugger;
5787 }
5788 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005789
Christopher Tate181fafa2009-05-14 11:12:14 -07005790 // If the app is being launched for restore or full backup, set it up specially
5791 boolean isRestrictedBackupMode = false;
5792 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5793 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5794 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5795 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005796
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005797 ensurePackageDexOpt(app.instrumentationInfo != null
5798 ? app.instrumentationInfo.packageName
5799 : app.info.packageName);
5800 if (app.instrumentationClass != null) {
5801 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005802 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005803 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005804 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005805 thread.bindApplication(processName, app.instrumentationInfo != null
5806 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005807 app.instrumentationClass, app.instrumentationProfileFile,
5808 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005809 isRestrictedBackupMode || !normalMode,
5810 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005811 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005812 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005813 } catch (Exception e) {
5814 // todo: Yikes! What should we do? For now we will try to
5815 // start another process, but that could easily get us in
5816 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005817 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818
5819 app.resetPackageList();
5820 startProcessLocked(app, "bind fail", processName);
5821 return false;
5822 }
5823
5824 // Remove this record from the list of starting applications.
5825 mPersistentStartingProcesses.remove(app);
5826 mProcessesOnHold.remove(app);
5827
5828 boolean badApp = false;
5829 boolean didSomething = false;
5830
5831 // See if the top visible activity is waiting to run in this process...
5832 HistoryRecord hr = topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07005833 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005834 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5835 && processName.equals(hr.processName)) {
5836 try {
5837 if (realStartActivityLocked(hr, app, true, true)) {
5838 didSomething = true;
5839 }
5840 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005841 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005842 + hr.intent.getComponent().flattenToShortString(), e);
5843 badApp = true;
5844 }
5845 } else {
5846 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5847 }
5848 }
5849
5850 // Find any services that should be running in this process...
5851 if (!badApp && mPendingServices.size() > 0) {
5852 ServiceRecord sr = null;
5853 try {
5854 for (int i=0; i<mPendingServices.size(); i++) {
5855 sr = mPendingServices.get(i);
5856 if (app.info.uid != sr.appInfo.uid
5857 || !processName.equals(sr.processName)) {
5858 continue;
5859 }
5860
5861 mPendingServices.remove(i);
5862 i--;
5863 realStartServiceLocked(sr, app);
5864 didSomething = true;
5865 }
5866 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005867 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 + sr.shortName, e);
5869 badApp = true;
5870 }
5871 }
5872
5873 // Check if the next broadcast receiver is in this process...
5874 BroadcastRecord br = mPendingBroadcast;
5875 if (!badApp && br != null && br.curApp == app) {
5876 try {
5877 mPendingBroadcast = null;
5878 processCurBroadcastLocked(br, app);
5879 didSomething = true;
5880 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005881 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005882 + br.curComponent.flattenToShortString(), e);
5883 badApp = true;
5884 logBroadcastReceiverDiscard(br);
5885 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5886 br.resultExtras, br.resultAbort, true);
5887 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005888 // We need to reset the state if we fails to start the receiver.
5889 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005890 }
5891 }
5892
Christopher Tate181fafa2009-05-14 11:12:14 -07005893 // Check whether the next backup agent is in this process...
5894 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005895 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005896 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005897 try {
5898 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5899 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005900 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005901 e.printStackTrace();
5902 }
5903 }
5904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005905 if (badApp) {
5906 // todo: Also need to kill application to deal with all
5907 // kinds of exceptions.
5908 handleAppDiedLocked(app, false);
5909 return false;
5910 }
5911
5912 if (!didSomething) {
5913 updateOomAdjLocked();
5914 }
5915
5916 return true;
5917 }
5918
5919 public final void attachApplication(IApplicationThread thread) {
5920 synchronized (this) {
5921 int callingPid = Binder.getCallingPid();
5922 final long origId = Binder.clearCallingIdentity();
5923 attachApplicationLocked(thread, callingPid);
5924 Binder.restoreCallingIdentity(origId);
5925 }
5926 }
5927
Dianne Hackborne88846e2009-09-30 21:34:25 -07005928 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005929 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005930 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 Binder.restoreCallingIdentity(origId);
5932 }
5933
5934 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5935 boolean remove) {
5936 int N = mStoppingActivities.size();
5937 if (N <= 0) return null;
5938
5939 ArrayList<HistoryRecord> stops = null;
5940
5941 final boolean nowVisible = mResumedActivity != null
5942 && mResumedActivity.nowVisible
5943 && !mResumedActivity.waitingVisible;
5944 for (int i=0; i<N; i++) {
5945 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005946 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 + nowVisible + " waitingVisible=" + s.waitingVisible
5948 + " finishing=" + s.finishing);
5949 if (s.waitingVisible && nowVisible) {
5950 mWaitingVisibleActivities.remove(s);
5951 s.waitingVisible = false;
5952 if (s.finishing) {
5953 // If this activity is finishing, it is sitting on top of
5954 // everyone else but we now know it is no longer needed...
5955 // so get rid of it. Otherwise, we need to go through the
5956 // normal flow and hide it once we determine that it is
5957 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005958 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005959 mWindowManager.setAppVisibility(s, false);
5960 }
5961 }
5962 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005963 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 if (stops == null) {
5965 stops = new ArrayList<HistoryRecord>();
5966 }
5967 stops.add(s);
5968 mStoppingActivities.remove(i);
5969 N--;
5970 i--;
5971 }
5972 }
5973
5974 return stops;
5975 }
5976
5977 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005978 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005979 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005980 mWindowManager.enableScreenAfterBoot();
5981 }
5982
Dianne Hackborne88846e2009-09-30 21:34:25 -07005983 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5984 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005985 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005986
5987 ArrayList<HistoryRecord> stops = null;
5988 ArrayList<HistoryRecord> finishes = null;
5989 ArrayList<HistoryRecord> thumbnails = null;
5990 int NS = 0;
5991 int NF = 0;
5992 int NT = 0;
5993 IApplicationThread sendThumbnail = null;
5994 boolean booting = false;
5995 boolean enableScreen = false;
5996
5997 synchronized (this) {
5998 if (token != null) {
5999 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
6000 }
6001
6002 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07006003 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006004 if (index >= 0) {
6005 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6006
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006007 if (fromTimeout) {
6008 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
6009 }
6010
Dianne Hackborne88846e2009-09-30 21:34:25 -07006011 // This is a hack to semi-deal with a race condition
6012 // in the client where it can be constructed with a
6013 // newer configuration from when we asked it to launch.
6014 // We'll update with whatever configuration it now says
6015 // it used to launch.
6016 if (config != null) {
6017 r.configuration = config;
6018 }
6019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 // No longer need to keep the device awake.
6021 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
6022 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
6023 mLaunchingActivity.release();
6024 }
6025
6026 // We are now idle. If someone is waiting for a thumbnail from
6027 // us, we can now deliver.
6028 r.idle = true;
6029 scheduleAppGcsLocked();
6030 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
6031 sendThumbnail = r.app.thread;
6032 r.thumbnailNeeded = false;
6033 }
6034
6035 // If this activity is fullscreen, set up to hide those under it.
6036
Joe Onorato8a9b2202010-02-26 18:56:32 -08006037 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038 ensureActivitiesVisibleLocked(null, 0);
6039
Joe Onorato8a9b2202010-02-26 18:56:32 -08006040 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 if (!mBooted && !fromTimeout) {
6042 mBooted = true;
6043 enableScreen = true;
6044 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006045
6046 } else if (fromTimeout) {
6047 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 }
6049
6050 // Atomically retrieve all of the other things to do.
6051 stops = processStoppingActivitiesLocked(true);
6052 NS = stops != null ? stops.size() : 0;
6053 if ((NF=mFinishingActivities.size()) > 0) {
6054 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
6055 mFinishingActivities.clear();
6056 }
6057 if ((NT=mCancelledThumbnails.size()) > 0) {
6058 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
6059 mCancelledThumbnails.clear();
6060 }
6061
6062 booting = mBooting;
6063 mBooting = false;
6064 }
6065
6066 int i;
6067
6068 // Send thumbnail if requested.
6069 if (sendThumbnail != null) {
6070 try {
6071 sendThumbnail.requestThumbnail(token);
6072 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006073 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006074 sendPendingThumbnail(null, token, null, null, true);
6075 }
6076 }
6077
6078 // Stop any activities that are scheduled to do so but have been
6079 // waiting for the next one to start.
6080 for (i=0; i<NS; i++) {
6081 HistoryRecord r = (HistoryRecord)stops.get(i);
6082 synchronized (this) {
6083 if (r.finishing) {
6084 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
6085 } else {
6086 stopActivityLocked(r);
6087 }
6088 }
6089 }
6090
6091 // Finish any activities that are scheduled to do so but have been
6092 // waiting for the next one to start.
6093 for (i=0; i<NF; i++) {
6094 HistoryRecord r = (HistoryRecord)finishes.get(i);
6095 synchronized (this) {
6096 destroyActivityLocked(r, true);
6097 }
6098 }
6099
6100 // Report back to any thumbnail receivers.
6101 for (i=0; i<NT; i++) {
6102 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
6103 sendPendingThumbnail(r, null, null, null, true);
6104 }
6105
6106 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006107 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006108 }
6109
6110 trimApplications();
6111 //dump();
6112 //mWindowManager.dump();
6113
6114 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 enableScreenAfterBoot();
6116 }
6117 }
6118
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006119 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006120 IntentFilter pkgFilter = new IntentFilter();
6121 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
6122 pkgFilter.addDataScheme("package");
6123 mContext.registerReceiver(new BroadcastReceiver() {
6124 @Override
6125 public void onReceive(Context context, Intent intent) {
6126 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
6127 if (pkgs != null) {
6128 for (String pkg : pkgs) {
6129 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
6130 setResultCode(Activity.RESULT_OK);
6131 return;
6132 }
6133 }
6134 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006135 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006136 }, pkgFilter);
6137
6138 synchronized (this) {
6139 // Ensure that any processes we had put on hold are now started
6140 // up.
6141 final int NP = mProcessesOnHold.size();
6142 if (NP > 0) {
6143 ArrayList<ProcessRecord> procs =
6144 new ArrayList<ProcessRecord>(mProcessesOnHold);
6145 for (int ip=0; ip<NP; ip++) {
6146 this.startProcessLocked(procs.get(ip), "on-hold", null);
6147 }
6148 }
6149
6150 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6151 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006152 broadcastIntentLocked(null, null,
6153 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
6154 null, null, 0, null, null,
6155 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
6156 false, false, MY_PID, Process.SYSTEM_UID);
6157 }
6158 }
6159 }
6160
6161 final void ensureBootCompleted() {
6162 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006163 boolean enableScreen;
6164 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006165 booting = mBooting;
6166 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006167 enableScreen = !mBooted;
6168 mBooted = true;
6169 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006170
6171 if (booting) {
6172 finishBooting();
6173 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006174
6175 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006176 enableScreenAfterBoot();
6177 }
6178 }
6179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006180 public final void activityPaused(IBinder token, Bundle icicle) {
6181 // Refuse possible leaked file descriptors
6182 if (icicle != null && icicle.hasFileDescriptors()) {
6183 throw new IllegalArgumentException("File descriptors passed in Bundle");
6184 }
6185
6186 final long origId = Binder.clearCallingIdentity();
6187 activityPaused(token, icicle, false);
6188 Binder.restoreCallingIdentity(origId);
6189 }
6190
6191 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006192 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006193 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
6194 + ", timeout=" + timeout);
6195
6196 HistoryRecord r = null;
6197
6198 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006199 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006200 if (index >= 0) {
6201 r = (HistoryRecord)mHistory.get(index);
6202 if (!timeout) {
6203 r.icicle = icicle;
6204 r.haveState = true;
6205 }
6206 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
6207 if (mPausingActivity == r) {
6208 r.state = ActivityState.PAUSED;
6209 completePauseLocked();
6210 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08006211 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006212 System.identityHashCode(r), r.shortComponentName,
6213 mPausingActivity != null
6214 ? mPausingActivity.shortComponentName : "(none)");
6215 }
6216 }
6217 }
6218 }
6219
6220 public final void activityStopped(IBinder token, Bitmap thumbnail,
6221 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006222 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006223 TAG, "Activity stopped: token=" + token);
6224
6225 HistoryRecord r = null;
6226
6227 final long origId = Binder.clearCallingIdentity();
6228
6229 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006230 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006231 if (index >= 0) {
6232 r = (HistoryRecord)mHistory.get(index);
6233 r.thumbnail = thumbnail;
6234 r.description = description;
6235 r.stopped = true;
6236 r.state = ActivityState.STOPPED;
6237 if (!r.finishing) {
6238 if (r.configDestroy) {
6239 destroyActivityLocked(r, true);
6240 resumeTopActivityLocked(null);
6241 }
6242 }
6243 }
6244 }
6245
6246 if (r != null) {
6247 sendPendingThumbnail(r, null, null, null, false);
6248 }
6249
6250 trimApplications();
6251
6252 Binder.restoreCallingIdentity(origId);
6253 }
6254
6255 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006256 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006257 synchronized (this) {
6258 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
6259
Dianne Hackborn75b03852009-06-12 15:43:26 -07006260 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006261 if (index >= 0) {
6262 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6263 if (r.state == ActivityState.DESTROYING) {
6264 final long origId = Binder.clearCallingIdentity();
6265 removeActivityFromHistoryLocked(r);
6266 Binder.restoreCallingIdentity(origId);
6267 }
6268 }
6269 }
6270 }
6271
6272 public String getCallingPackage(IBinder token) {
6273 synchronized (this) {
6274 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07006275 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006276 }
6277 }
6278
6279 public ComponentName getCallingActivity(IBinder token) {
6280 synchronized (this) {
6281 HistoryRecord r = getCallingRecordLocked(token);
6282 return r != null ? r.intent.getComponent() : null;
6283 }
6284 }
6285
6286 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006287 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006288 if (index >= 0) {
6289 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6290 if (r != null) {
6291 return r.resultTo;
6292 }
6293 }
6294 return null;
6295 }
6296
6297 public ComponentName getActivityClassForToken(IBinder token) {
6298 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006299 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006300 if (index >= 0) {
6301 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6302 return r.intent.getComponent();
6303 }
6304 return null;
6305 }
6306 }
6307
6308 public String getPackageForToken(IBinder token) {
6309 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006310 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006311 if (index >= 0) {
6312 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6313 return r.packageName;
6314 }
6315 return null;
6316 }
6317 }
6318
6319 public IIntentSender getIntentSender(int type,
6320 String packageName, IBinder token, String resultWho,
6321 int requestCode, Intent intent, String resolvedType, int flags) {
6322 // Refuse possible leaked file descriptors
6323 if (intent != null && intent.hasFileDescriptors() == true) {
6324 throw new IllegalArgumentException("File descriptors passed in Intent");
6325 }
6326
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006327 if (type == INTENT_SENDER_BROADCAST) {
6328 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6329 throw new IllegalArgumentException(
6330 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6331 }
6332 }
6333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006334 synchronized(this) {
6335 int callingUid = Binder.getCallingUid();
6336 try {
6337 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6338 Process.supportsProcesses()) {
6339 int uid = ActivityThread.getPackageManager()
6340 .getPackageUid(packageName);
6341 if (uid != Binder.getCallingUid()) {
6342 String msg = "Permission Denial: getIntentSender() from pid="
6343 + Binder.getCallingPid()
6344 + ", uid=" + Binder.getCallingUid()
6345 + ", (need uid=" + uid + ")"
6346 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006347 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006348 throw new SecurityException(msg);
6349 }
6350 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006351
6352 return getIntentSenderLocked(type, packageName, callingUid,
6353 token, resultWho, requestCode, intent, resolvedType, flags);
6354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006355 } catch (RemoteException e) {
6356 throw new SecurityException(e);
6357 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006358 }
6359 }
6360
6361 IIntentSender getIntentSenderLocked(int type,
6362 String packageName, int callingUid, IBinder token, String resultWho,
6363 int requestCode, Intent intent, String resolvedType, int flags) {
6364 HistoryRecord activity = null;
6365 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6366 int index = indexOfTokenLocked(token);
6367 if (index < 0) {
6368 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006369 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006370 activity = (HistoryRecord)mHistory.get(index);
6371 if (activity.finishing) {
6372 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006373 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006374 }
6375
6376 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6377 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6378 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6379 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6380 |PendingIntent.FLAG_UPDATE_CURRENT);
6381
6382 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6383 type, packageName, activity, resultWho,
6384 requestCode, intent, resolvedType, flags);
6385 WeakReference<PendingIntentRecord> ref;
6386 ref = mIntentSenderRecords.get(key);
6387 PendingIntentRecord rec = ref != null ? ref.get() : null;
6388 if (rec != null) {
6389 if (!cancelCurrent) {
6390 if (updateCurrent) {
6391 rec.key.requestIntent.replaceExtras(intent);
6392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006393 return rec;
6394 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006395 rec.canceled = true;
6396 mIntentSenderRecords.remove(key);
6397 }
6398 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006399 return rec;
6400 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006401 rec = new PendingIntentRecord(this, key, callingUid);
6402 mIntentSenderRecords.put(key, rec.ref);
6403 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6404 if (activity.pendingResults == null) {
6405 activity.pendingResults
6406 = new HashSet<WeakReference<PendingIntentRecord>>();
6407 }
6408 activity.pendingResults.add(rec.ref);
6409 }
6410 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006411 }
6412
6413 public void cancelIntentSender(IIntentSender sender) {
6414 if (!(sender instanceof PendingIntentRecord)) {
6415 return;
6416 }
6417 synchronized(this) {
6418 PendingIntentRecord rec = (PendingIntentRecord)sender;
6419 try {
6420 int uid = ActivityThread.getPackageManager()
6421 .getPackageUid(rec.key.packageName);
6422 if (uid != Binder.getCallingUid()) {
6423 String msg = "Permission Denial: cancelIntentSender() from pid="
6424 + Binder.getCallingPid()
6425 + ", uid=" + Binder.getCallingUid()
6426 + " is not allowed to cancel packges "
6427 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006428 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006429 throw new SecurityException(msg);
6430 }
6431 } catch (RemoteException e) {
6432 throw new SecurityException(e);
6433 }
6434 cancelIntentSenderLocked(rec, true);
6435 }
6436 }
6437
6438 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6439 rec.canceled = true;
6440 mIntentSenderRecords.remove(rec.key);
6441 if (cleanActivity && rec.key.activity != null) {
6442 rec.key.activity.pendingResults.remove(rec.ref);
6443 }
6444 }
6445
6446 public String getPackageForIntentSender(IIntentSender pendingResult) {
6447 if (!(pendingResult instanceof PendingIntentRecord)) {
6448 return null;
6449 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006450 try {
6451 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6452 return res.key.packageName;
6453 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006454 }
6455 return null;
6456 }
6457
6458 public void setProcessLimit(int max) {
6459 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6460 "setProcessLimit()");
6461 mProcessLimit = max;
6462 }
6463
6464 public int getProcessLimit() {
6465 return mProcessLimit;
6466 }
6467
6468 void foregroundTokenDied(ForegroundToken token) {
6469 synchronized (ActivityManagerService.this) {
6470 synchronized (mPidsSelfLocked) {
6471 ForegroundToken cur
6472 = mForegroundProcesses.get(token.pid);
6473 if (cur != token) {
6474 return;
6475 }
6476 mForegroundProcesses.remove(token.pid);
6477 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6478 if (pr == null) {
6479 return;
6480 }
6481 pr.forcingToForeground = null;
6482 pr.foregroundServices = false;
6483 }
6484 updateOomAdjLocked();
6485 }
6486 }
6487
6488 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6489 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6490 "setProcessForeground()");
6491 synchronized(this) {
6492 boolean changed = false;
6493
6494 synchronized (mPidsSelfLocked) {
6495 ProcessRecord pr = mPidsSelfLocked.get(pid);
6496 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006497 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006498 return;
6499 }
6500 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6501 if (oldToken != null) {
6502 oldToken.token.unlinkToDeath(oldToken, 0);
6503 mForegroundProcesses.remove(pid);
6504 pr.forcingToForeground = null;
6505 changed = true;
6506 }
6507 if (isForeground && token != null) {
6508 ForegroundToken newToken = new ForegroundToken() {
6509 public void binderDied() {
6510 foregroundTokenDied(this);
6511 }
6512 };
6513 newToken.pid = pid;
6514 newToken.token = token;
6515 try {
6516 token.linkToDeath(newToken, 0);
6517 mForegroundProcesses.put(pid, newToken);
6518 pr.forcingToForeground = token;
6519 changed = true;
6520 } catch (RemoteException e) {
6521 // If the process died while doing this, we will later
6522 // do the cleanup with the process death link.
6523 }
6524 }
6525 }
6526
6527 if (changed) {
6528 updateOomAdjLocked();
6529 }
6530 }
6531 }
6532
6533 // =========================================================
6534 // PERMISSIONS
6535 // =========================================================
6536
6537 static class PermissionController extends IPermissionController.Stub {
6538 ActivityManagerService mActivityManagerService;
6539 PermissionController(ActivityManagerService activityManagerService) {
6540 mActivityManagerService = activityManagerService;
6541 }
6542
6543 public boolean checkPermission(String permission, int pid, int uid) {
6544 return mActivityManagerService.checkPermission(permission, pid,
6545 uid) == PackageManager.PERMISSION_GRANTED;
6546 }
6547 }
6548
6549 /**
6550 * This can be called with or without the global lock held.
6551 */
6552 int checkComponentPermission(String permission, int pid, int uid,
6553 int reqUid) {
6554 // We might be performing an operation on behalf of an indirect binder
6555 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6556 // client identity accordingly before proceeding.
6557 Identity tlsIdentity = sCallerIdentity.get();
6558 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006559 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006560 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6561 uid = tlsIdentity.uid;
6562 pid = tlsIdentity.pid;
6563 }
6564
6565 // Root, system server and our own process get to do everything.
6566 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6567 !Process.supportsProcesses()) {
6568 return PackageManager.PERMISSION_GRANTED;
6569 }
6570 // If the target requires a specific UID, always fail for others.
6571 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006572 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006573 return PackageManager.PERMISSION_DENIED;
6574 }
6575 if (permission == null) {
6576 return PackageManager.PERMISSION_GRANTED;
6577 }
6578 try {
6579 return ActivityThread.getPackageManager()
6580 .checkUidPermission(permission, uid);
6581 } catch (RemoteException e) {
6582 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006583 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 }
6585 return PackageManager.PERMISSION_DENIED;
6586 }
6587
6588 /**
6589 * As the only public entry point for permissions checking, this method
6590 * can enforce the semantic that requesting a check on a null global
6591 * permission is automatically denied. (Internally a null permission
6592 * string is used when calling {@link #checkComponentPermission} in cases
6593 * when only uid-based security is needed.)
6594 *
6595 * This can be called with or without the global lock held.
6596 */
6597 public int checkPermission(String permission, int pid, int uid) {
6598 if (permission == null) {
6599 return PackageManager.PERMISSION_DENIED;
6600 }
6601 return checkComponentPermission(permission, pid, uid, -1);
6602 }
6603
6604 /**
6605 * Binder IPC calls go through the public entry point.
6606 * This can be called with or without the global lock held.
6607 */
6608 int checkCallingPermission(String permission) {
6609 return checkPermission(permission,
6610 Binder.getCallingPid(),
6611 Binder.getCallingUid());
6612 }
6613
6614 /**
6615 * This can be called with or without the global lock held.
6616 */
6617 void enforceCallingPermission(String permission, String func) {
6618 if (checkCallingPermission(permission)
6619 == PackageManager.PERMISSION_GRANTED) {
6620 return;
6621 }
6622
6623 String msg = "Permission Denial: " + func + " from pid="
6624 + Binder.getCallingPid()
6625 + ", uid=" + Binder.getCallingUid()
6626 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006627 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006628 throw new SecurityException(msg);
6629 }
6630
6631 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6632 ProviderInfo pi, int uid, int modeFlags) {
6633 try {
6634 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6635 if ((pi.readPermission != null) &&
6636 (pm.checkUidPermission(pi.readPermission, uid)
6637 != PackageManager.PERMISSION_GRANTED)) {
6638 return false;
6639 }
6640 }
6641 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6642 if ((pi.writePermission != null) &&
6643 (pm.checkUidPermission(pi.writePermission, uid)
6644 != PackageManager.PERMISSION_GRANTED)) {
6645 return false;
6646 }
6647 }
6648 return true;
6649 } catch (RemoteException e) {
6650 return false;
6651 }
6652 }
6653
6654 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6655 int modeFlags) {
6656 // Root gets to do everything.
6657 if (uid == 0 || !Process.supportsProcesses()) {
6658 return true;
6659 }
6660 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6661 if (perms == null) return false;
6662 UriPermission perm = perms.get(uri);
6663 if (perm == null) return false;
6664 return (modeFlags&perm.modeFlags) == modeFlags;
6665 }
6666
6667 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6668 // Another redirected-binder-call permissions check as in
6669 // {@link checkComponentPermission}.
6670 Identity tlsIdentity = sCallerIdentity.get();
6671 if (tlsIdentity != null) {
6672 uid = tlsIdentity.uid;
6673 pid = tlsIdentity.pid;
6674 }
6675
6676 // Our own process gets to do everything.
6677 if (pid == MY_PID) {
6678 return PackageManager.PERMISSION_GRANTED;
6679 }
6680 synchronized(this) {
6681 return checkUriPermissionLocked(uri, uid, modeFlags)
6682 ? PackageManager.PERMISSION_GRANTED
6683 : PackageManager.PERMISSION_DENIED;
6684 }
6685 }
6686
6687 private void grantUriPermissionLocked(int callingUid,
6688 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6689 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6690 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6691 if (modeFlags == 0) {
6692 return;
6693 }
6694
Joe Onorato8a9b2202010-02-26 18:56:32 -08006695 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006696 "Requested grant " + targetPkg + " permission to " + uri);
6697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006698 final IPackageManager pm = ActivityThread.getPackageManager();
6699
6700 // If this is not a content: uri, we can't do anything with it.
6701 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006702 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006703 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006704 return;
6705 }
6706
6707 String name = uri.getAuthority();
6708 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006709 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006710 if (cpr != null) {
6711 pi = cpr.info;
6712 } else {
6713 try {
6714 pi = pm.resolveContentProvider(name,
6715 PackageManager.GET_URI_PERMISSION_PATTERNS);
6716 } catch (RemoteException ex) {
6717 }
6718 }
6719 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006720 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006721 return;
6722 }
6723
6724 int targetUid;
6725 try {
6726 targetUid = pm.getPackageUid(targetPkg);
6727 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006728 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006729 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006730 return;
6731 }
6732 } catch (RemoteException ex) {
6733 return;
6734 }
6735
6736 // First... does the target actually need this permission?
6737 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6738 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006739 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006740 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006741 return;
6742 }
6743
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006744 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006745 if (!pi.grantUriPermissions) {
6746 throw new SecurityException("Provider " + pi.packageName
6747 + "/" + pi.name
6748 + " does not allow granting of Uri permissions (uri "
6749 + uri + ")");
6750 }
6751 if (pi.uriPermissionPatterns != null) {
6752 final int N = pi.uriPermissionPatterns.length;
6753 boolean allowed = false;
6754 for (int i=0; i<N; i++) {
6755 if (pi.uriPermissionPatterns[i] != null
6756 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6757 allowed = true;
6758 break;
6759 }
6760 }
6761 if (!allowed) {
6762 throw new SecurityException("Provider " + pi.packageName
6763 + "/" + pi.name
6764 + " does not allow granting of permission to path of Uri "
6765 + uri);
6766 }
6767 }
6768
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006769 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006770 // this uri?
6771 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6772 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6773 throw new SecurityException("Uid " + callingUid
6774 + " does not have permission to uri " + uri);
6775 }
6776 }
6777
6778 // Okay! So here we are: the caller has the assumed permission
6779 // to the uri, and the target doesn't. Let's now give this to
6780 // the target.
6781
Joe Onorato8a9b2202010-02-26 18:56:32 -08006782 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006783 "Granting " + targetPkg + " permission to " + uri);
6784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006785 HashMap<Uri, UriPermission> targetUris
6786 = mGrantedUriPermissions.get(targetUid);
6787 if (targetUris == null) {
6788 targetUris = new HashMap<Uri, UriPermission>();
6789 mGrantedUriPermissions.put(targetUid, targetUris);
6790 }
6791
6792 UriPermission perm = targetUris.get(uri);
6793 if (perm == null) {
6794 perm = new UriPermission(targetUid, uri);
6795 targetUris.put(uri, perm);
6796
6797 }
6798 perm.modeFlags |= modeFlags;
6799 if (activity == null) {
6800 perm.globalModeFlags |= modeFlags;
6801 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6802 perm.readActivities.add(activity);
6803 if (activity.readUriPermissions == null) {
6804 activity.readUriPermissions = new HashSet<UriPermission>();
6805 }
6806 activity.readUriPermissions.add(perm);
6807 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6808 perm.writeActivities.add(activity);
6809 if (activity.writeUriPermissions == null) {
6810 activity.writeUriPermissions = new HashSet<UriPermission>();
6811 }
6812 activity.writeUriPermissions.add(perm);
6813 }
6814 }
6815
6816 private void grantUriPermissionFromIntentLocked(int callingUid,
6817 String targetPkg, Intent intent, HistoryRecord activity) {
6818 if (intent == null) {
6819 return;
6820 }
6821 Uri data = intent.getData();
6822 if (data == null) {
6823 return;
6824 }
6825 grantUriPermissionLocked(callingUid, targetPkg, data,
6826 intent.getFlags(), activity);
6827 }
6828
6829 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6830 Uri uri, int modeFlags) {
6831 synchronized(this) {
6832 final ProcessRecord r = getRecordForAppLocked(caller);
6833 if (r == null) {
6834 throw new SecurityException("Unable to find app for caller "
6835 + caller
6836 + " when granting permission to uri " + uri);
6837 }
6838 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006839 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006840 return;
6841 }
6842 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006843 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006844 return;
6845 }
6846
6847 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6848 null);
6849 }
6850 }
6851
6852 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6853 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6854 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6855 HashMap<Uri, UriPermission> perms
6856 = mGrantedUriPermissions.get(perm.uid);
6857 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006858 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006859 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006860 perms.remove(perm.uri);
6861 if (perms.size() == 0) {
6862 mGrantedUriPermissions.remove(perm.uid);
6863 }
6864 }
6865 }
6866 }
6867
6868 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6869 if (activity.readUriPermissions != null) {
6870 for (UriPermission perm : activity.readUriPermissions) {
6871 perm.readActivities.remove(activity);
6872 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6873 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6874 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6875 removeUriPermissionIfNeededLocked(perm);
6876 }
6877 }
6878 }
6879 if (activity.writeUriPermissions != null) {
6880 for (UriPermission perm : activity.writeUriPermissions) {
6881 perm.writeActivities.remove(activity);
6882 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6883 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6884 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6885 removeUriPermissionIfNeededLocked(perm);
6886 }
6887 }
6888 }
6889 }
6890
6891 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6892 int modeFlags) {
6893 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6894 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6895 if (modeFlags == 0) {
6896 return;
6897 }
6898
Joe Onorato8a9b2202010-02-26 18:56:32 -08006899 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006900 "Revoking all granted permissions to " + uri);
6901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006902 final IPackageManager pm = ActivityThread.getPackageManager();
6903
6904 final String authority = uri.getAuthority();
6905 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006906 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006907 if (cpr != null) {
6908 pi = cpr.info;
6909 } else {
6910 try {
6911 pi = pm.resolveContentProvider(authority,
6912 PackageManager.GET_URI_PERMISSION_PATTERNS);
6913 } catch (RemoteException ex) {
6914 }
6915 }
6916 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006917 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006918 return;
6919 }
6920
6921 // Does the caller have this permission on the URI?
6922 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6923 // Right now, if you are not the original owner of the permission,
6924 // you are not allowed to revoke it.
6925 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6926 throw new SecurityException("Uid " + callingUid
6927 + " does not have permission to uri " + uri);
6928 //}
6929 }
6930
6931 // Go through all of the permissions and remove any that match.
6932 final List<String> SEGMENTS = uri.getPathSegments();
6933 if (SEGMENTS != null) {
6934 final int NS = SEGMENTS.size();
6935 int N = mGrantedUriPermissions.size();
6936 for (int i=0; i<N; i++) {
6937 HashMap<Uri, UriPermission> perms
6938 = mGrantedUriPermissions.valueAt(i);
6939 Iterator<UriPermission> it = perms.values().iterator();
6940 toploop:
6941 while (it.hasNext()) {
6942 UriPermission perm = it.next();
6943 Uri targetUri = perm.uri;
6944 if (!authority.equals(targetUri.getAuthority())) {
6945 continue;
6946 }
6947 List<String> targetSegments = targetUri.getPathSegments();
6948 if (targetSegments == null) {
6949 continue;
6950 }
6951 if (targetSegments.size() < NS) {
6952 continue;
6953 }
6954 for (int j=0; j<NS; j++) {
6955 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6956 continue toploop;
6957 }
6958 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006959 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006960 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006961 perm.clearModes(modeFlags);
6962 if (perm.modeFlags == 0) {
6963 it.remove();
6964 }
6965 }
6966 if (perms.size() == 0) {
6967 mGrantedUriPermissions.remove(
6968 mGrantedUriPermissions.keyAt(i));
6969 N--;
6970 i--;
6971 }
6972 }
6973 }
6974 }
6975
6976 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6977 int modeFlags) {
6978 synchronized(this) {
6979 final ProcessRecord r = getRecordForAppLocked(caller);
6980 if (r == null) {
6981 throw new SecurityException("Unable to find app for caller "
6982 + caller
6983 + " when revoking permission to uri " + uri);
6984 }
6985 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006986 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006987 return;
6988 }
6989
6990 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6991 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6992 if (modeFlags == 0) {
6993 return;
6994 }
6995
6996 final IPackageManager pm = ActivityThread.getPackageManager();
6997
6998 final String authority = uri.getAuthority();
6999 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07007000 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007001 if (cpr != null) {
7002 pi = cpr.info;
7003 } else {
7004 try {
7005 pi = pm.resolveContentProvider(authority,
7006 PackageManager.GET_URI_PERMISSION_PATTERNS);
7007 } catch (RemoteException ex) {
7008 }
7009 }
7010 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007011 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007012 return;
7013 }
7014
7015 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
7016 }
7017 }
7018
7019 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
7020 synchronized (this) {
7021 ProcessRecord app =
7022 who != null ? getRecordForAppLocked(who) : null;
7023 if (app == null) return;
7024
7025 Message msg = Message.obtain();
7026 msg.what = WAIT_FOR_DEBUGGER_MSG;
7027 msg.obj = app;
7028 msg.arg1 = waiting ? 1 : 0;
7029 mHandler.sendMessage(msg);
7030 }
7031 }
7032
7033 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
7034 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08007035 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007036 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08007037 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007038 }
7039
7040 // =========================================================
7041 // TASK MANAGEMENT
7042 // =========================================================
7043
7044 public List getTasks(int maxNum, int flags,
7045 IThumbnailReceiver receiver) {
7046 ArrayList list = new ArrayList();
7047
7048 PendingThumbnailsRecord pending = null;
7049 IApplicationThread topThumbnail = null;
7050 HistoryRecord topRecord = null;
7051
7052 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007053 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007054 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
7055 + ", receiver=" + receiver);
7056
7057 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
7058 != PackageManager.PERMISSION_GRANTED) {
7059 if (receiver != null) {
7060 // If the caller wants to wait for pending thumbnails,
7061 // it ain't gonna get them.
7062 try {
7063 receiver.finished();
7064 } catch (RemoteException ex) {
7065 }
7066 }
7067 String msg = "Permission Denial: getTasks() from pid="
7068 + Binder.getCallingPid()
7069 + ", uid=" + Binder.getCallingUid()
7070 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007071 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007072 throw new SecurityException(msg);
7073 }
7074
7075 int pos = mHistory.size()-1;
7076 HistoryRecord next =
7077 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
7078 HistoryRecord top = null;
7079 CharSequence topDescription = null;
7080 TaskRecord curTask = null;
7081 int numActivities = 0;
7082 int numRunning = 0;
7083 while (pos >= 0 && maxNum > 0) {
7084 final HistoryRecord r = next;
7085 pos--;
7086 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
7087
7088 // Initialize state for next task if needed.
7089 if (top == null ||
7090 (top.state == ActivityState.INITIALIZING
7091 && top.task == r.task)) {
7092 top = r;
7093 topDescription = r.description;
7094 curTask = r.task;
7095 numActivities = numRunning = 0;
7096 }
7097
7098 // Add 'r' into the current task.
7099 numActivities++;
7100 if (r.app != null && r.app.thread != null) {
7101 numRunning++;
7102 }
7103 if (topDescription == null) {
7104 topDescription = r.description;
7105 }
7106
Joe Onorato8a9b2202010-02-26 18:56:32 -08007107 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007108 TAG, r.intent.getComponent().flattenToShortString()
7109 + ": task=" + r.task);
7110
7111 // If the next one is a different task, generate a new
7112 // TaskInfo entry for what we have.
7113 if (next == null || next.task != curTask) {
7114 ActivityManager.RunningTaskInfo ci
7115 = new ActivityManager.RunningTaskInfo();
7116 ci.id = curTask.taskId;
7117 ci.baseActivity = r.intent.getComponent();
7118 ci.topActivity = top.intent.getComponent();
7119 ci.thumbnail = top.thumbnail;
7120 ci.description = topDescription;
7121 ci.numActivities = numActivities;
7122 ci.numRunning = numRunning;
7123 //System.out.println(
7124 // "#" + maxNum + ": " + " descr=" + ci.description);
7125 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007126 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007127 TAG, "State=" + top.state + "Idle=" + top.idle
7128 + " app=" + top.app
7129 + " thr=" + (top.app != null ? top.app.thread : null));
7130 if (top.state == ActivityState.RESUMED
7131 || top.state == ActivityState.PAUSING) {
7132 if (top.idle && top.app != null
7133 && top.app.thread != null) {
7134 topRecord = top;
7135 topThumbnail = top.app.thread;
7136 } else {
7137 top.thumbnailNeeded = true;
7138 }
7139 }
7140 if (pending == null) {
7141 pending = new PendingThumbnailsRecord(receiver);
7142 }
7143 pending.pendingRecords.add(top);
7144 }
7145 list.add(ci);
7146 maxNum--;
7147 top = null;
7148 }
7149 }
7150
7151 if (pending != null) {
7152 mPendingThumbnails.add(pending);
7153 }
7154 }
7155
Joe Onorato8a9b2202010-02-26 18:56:32 -08007156 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007157
7158 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007159 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007160 try {
7161 topThumbnail.requestThumbnail(topRecord);
7162 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007163 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007164 sendPendingThumbnail(null, topRecord, null, null, true);
7165 }
7166 }
7167
7168 if (pending == null && receiver != null) {
7169 // In this case all thumbnails were available and the client
7170 // is being asked to be told when the remaining ones come in...
7171 // which is unusually, since the top-most currently running
7172 // activity should never have a canned thumbnail! Oh well.
7173 try {
7174 receiver.finished();
7175 } catch (RemoteException ex) {
7176 }
7177 }
7178
7179 return list;
7180 }
7181
7182 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
7183 int flags) {
7184 synchronized (this) {
7185 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
7186 "getRecentTasks()");
7187
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007188 IPackageManager pm = ActivityThread.getPackageManager();
7189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007190 final int N = mRecentTasks.size();
7191 ArrayList<ActivityManager.RecentTaskInfo> res
7192 = new ArrayList<ActivityManager.RecentTaskInfo>(
7193 maxNum < N ? maxNum : N);
7194 for (int i=0; i<N && maxNum > 0; i++) {
7195 TaskRecord tr = mRecentTasks.get(i);
7196 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
7197 || (tr.intent == null)
7198 || ((tr.intent.getFlags()
7199 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
7200 ActivityManager.RecentTaskInfo rti
7201 = new ActivityManager.RecentTaskInfo();
7202 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
7203 rti.baseIntent = new Intent(
7204 tr.intent != null ? tr.intent : tr.affinityIntent);
7205 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007206
7207 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
7208 // Check whether this activity is currently available.
7209 try {
7210 if (rti.origActivity != null) {
7211 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
7212 continue;
7213 }
7214 } else if (rti.baseIntent != null) {
7215 if (pm.queryIntentActivities(rti.baseIntent,
7216 null, 0) == null) {
7217 continue;
7218 }
7219 }
7220 } catch (RemoteException e) {
7221 // Will never happen.
7222 }
7223 }
7224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007225 res.add(rti);
7226 maxNum--;
7227 }
7228 }
7229 return res;
7230 }
7231 }
7232
7233 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
7234 int j;
7235 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
7236 TaskRecord jt = startTask;
7237
7238 // First look backwards
7239 for (j=startIndex-1; j>=0; j--) {
7240 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7241 if (r.task != jt) {
7242 jt = r.task;
7243 if (affinity.equals(jt.affinity)) {
7244 return j;
7245 }
7246 }
7247 }
7248
7249 // Now look forwards
7250 final int N = mHistory.size();
7251 jt = startTask;
7252 for (j=startIndex+1; j<N; j++) {
7253 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7254 if (r.task != jt) {
7255 if (affinity.equals(jt.affinity)) {
7256 return j;
7257 }
7258 jt = r.task;
7259 }
7260 }
7261
7262 // Might it be at the top?
7263 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
7264 return N-1;
7265 }
7266
7267 return -1;
7268 }
7269
7270 /**
7271 * Perform a reset of the given task, if needed as part of launching it.
7272 * Returns the new HistoryRecord at the top of the task.
7273 */
7274 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
7275 HistoryRecord newActivity) {
7276 boolean forceReset = (newActivity.info.flags
7277 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
7278 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
7279 if ((newActivity.info.flags
7280 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
7281 forceReset = true;
7282 }
7283 }
7284
7285 final TaskRecord task = taskTop.task;
7286
7287 // We are going to move through the history list so that we can look
7288 // at each activity 'target' with 'below' either the interesting
7289 // activity immediately below it in the stack or null.
7290 HistoryRecord target = null;
7291 int targetI = 0;
7292 int taskTopI = -1;
7293 int replyChainEnd = -1;
7294 int lastReparentPos = -1;
7295 for (int i=mHistory.size()-1; i>=-1; i--) {
7296 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
7297
7298 if (below != null && below.finishing) {
7299 continue;
7300 }
7301 if (target == null) {
7302 target = below;
7303 targetI = i;
7304 // If we were in the middle of a reply chain before this
7305 // task, it doesn't appear like the root of the chain wants
7306 // anything interesting, so drop it.
7307 replyChainEnd = -1;
7308 continue;
7309 }
7310
7311 final int flags = target.info.flags;
7312
7313 final boolean finishOnTaskLaunch =
7314 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7315 final boolean allowTaskReparenting =
7316 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7317
7318 if (target.task == task) {
7319 // We are inside of the task being reset... we'll either
7320 // finish this activity, push it out for another task,
7321 // or leave it as-is. We only do this
7322 // for activities that are not the root of the task (since
7323 // if we finish the root, we may no longer have the task!).
7324 if (taskTopI < 0) {
7325 taskTopI = targetI;
7326 }
7327 if (below != null && below.task == task) {
7328 final boolean clearWhenTaskReset =
7329 (target.intent.getFlags()
7330 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007331 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007332 // If this activity is sending a reply to a previous
7333 // activity, we can't do anything with it now until
7334 // we reach the start of the reply chain.
7335 // XXX note that we are assuming the result is always
7336 // to the previous activity, which is almost always
7337 // the case but we really shouldn't count on.
7338 if (replyChainEnd < 0) {
7339 replyChainEnd = targetI;
7340 }
Ed Heyl73798232009-03-24 21:32:21 -07007341 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007342 && target.taskAffinity != null
7343 && !target.taskAffinity.equals(task.affinity)) {
7344 // If this activity has an affinity for another
7345 // task, then we need to move it out of here. We will
7346 // move it as far out of the way as possible, to the
7347 // bottom of the activity stack. This also keeps it
7348 // correctly ordered with any activities we previously
7349 // moved.
7350 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7351 if (target.taskAffinity != null
7352 && target.taskAffinity.equals(p.task.affinity)) {
7353 // If the activity currently at the bottom has the
7354 // same task affinity as the one we are moving,
7355 // then merge it into the same task.
7356 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007357 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007358 + " out to bottom task " + p.task);
7359 } else {
7360 mCurTask++;
7361 if (mCurTask <= 0) {
7362 mCurTask = 1;
7363 }
7364 target.task = new TaskRecord(mCurTask, target.info, null,
7365 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7366 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007367 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 + " out to new task " + target.task);
7369 }
7370 mWindowManager.setAppGroupId(target, task.taskId);
7371 if (replyChainEnd < 0) {
7372 replyChainEnd = targetI;
7373 }
7374 int dstPos = 0;
7375 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7376 p = (HistoryRecord)mHistory.get(srcPos);
7377 if (p.finishing) {
7378 continue;
7379 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007380 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007381 + " out to target's task " + target.task);
7382 task.numActivities--;
7383 p.task = target.task;
7384 target.task.numActivities++;
7385 mHistory.remove(srcPos);
7386 mHistory.add(dstPos, p);
7387 mWindowManager.moveAppToken(dstPos, p);
7388 mWindowManager.setAppGroupId(p, p.task.taskId);
7389 dstPos++;
7390 if (VALIDATE_TOKENS) {
7391 mWindowManager.validateAppTokens(mHistory);
7392 }
7393 i++;
7394 }
7395 if (taskTop == p) {
7396 taskTop = below;
7397 }
7398 if (taskTopI == replyChainEnd) {
7399 taskTopI = -1;
7400 }
7401 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007402 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007403 } else if (forceReset || finishOnTaskLaunch
7404 || clearWhenTaskReset) {
7405 // If the activity should just be removed -- either
7406 // because it asks for it, or the task should be
7407 // cleared -- then finish it and anything that is
7408 // part of its reply chain.
7409 if (clearWhenTaskReset) {
7410 // In this case, we want to finish this activity
7411 // and everything above it, so be sneaky and pretend
7412 // like these are all in the reply chain.
7413 replyChainEnd = targetI+1;
7414 while (replyChainEnd < mHistory.size() &&
7415 ((HistoryRecord)mHistory.get(
7416 replyChainEnd)).task == task) {
7417 replyChainEnd++;
7418 }
7419 replyChainEnd--;
7420 } else if (replyChainEnd < 0) {
7421 replyChainEnd = targetI;
7422 }
7423 HistoryRecord p = null;
7424 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7425 p = (HistoryRecord)mHistory.get(srcPos);
7426 if (p.finishing) {
7427 continue;
7428 }
7429 if (finishActivityLocked(p, srcPos,
7430 Activity.RESULT_CANCELED, null, "reset")) {
7431 replyChainEnd--;
7432 srcPos--;
7433 }
7434 }
7435 if (taskTop == p) {
7436 taskTop = below;
7437 }
7438 if (taskTopI == replyChainEnd) {
7439 taskTopI = -1;
7440 }
7441 replyChainEnd = -1;
7442 } else {
7443 // If we were in the middle of a chain, well the
7444 // activity that started it all doesn't want anything
7445 // special, so leave it all as-is.
7446 replyChainEnd = -1;
7447 }
7448 } else {
7449 // Reached the bottom of the task -- any reply chain
7450 // should be left as-is.
7451 replyChainEnd = -1;
7452 }
7453
7454 } else if (target.resultTo != null) {
7455 // If this activity is sending a reply to a previous
7456 // activity, we can't do anything with it now until
7457 // we reach the start of the reply chain.
7458 // XXX note that we are assuming the result is always
7459 // to the previous activity, which is almost always
7460 // the case but we really shouldn't count on.
7461 if (replyChainEnd < 0) {
7462 replyChainEnd = targetI;
7463 }
7464
7465 } else if (taskTopI >= 0 && allowTaskReparenting
7466 && task.affinity != null
7467 && task.affinity.equals(target.taskAffinity)) {
7468 // We are inside of another task... if this activity has
7469 // an affinity for our task, then either remove it if we are
7470 // clearing or move it over to our task. Note that
7471 // we currently punt on the case where we are resetting a
7472 // task that is not at the top but who has activities above
7473 // with an affinity to it... this is really not a normal
7474 // case, and we will need to later pull that task to the front
7475 // and usually at that point we will do the reset and pick
7476 // up those remaining activities. (This only happens if
7477 // someone starts an activity in a new task from an activity
7478 // in a task that is not currently on top.)
7479 if (forceReset || finishOnTaskLaunch) {
7480 if (replyChainEnd < 0) {
7481 replyChainEnd = targetI;
7482 }
7483 HistoryRecord p = null;
7484 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7485 p = (HistoryRecord)mHistory.get(srcPos);
7486 if (p.finishing) {
7487 continue;
7488 }
7489 if (finishActivityLocked(p, srcPos,
7490 Activity.RESULT_CANCELED, null, "reset")) {
7491 taskTopI--;
7492 lastReparentPos--;
7493 replyChainEnd--;
7494 srcPos--;
7495 }
7496 }
7497 replyChainEnd = -1;
7498 } else {
7499 if (replyChainEnd < 0) {
7500 replyChainEnd = targetI;
7501 }
7502 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7503 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7504 if (p.finishing) {
7505 continue;
7506 }
7507 if (lastReparentPos < 0) {
7508 lastReparentPos = taskTopI;
7509 taskTop = p;
7510 } else {
7511 lastReparentPos--;
7512 }
7513 mHistory.remove(srcPos);
7514 p.task.numActivities--;
7515 p.task = task;
7516 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007517 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007518 + " in to resetting task " + task);
7519 task.numActivities++;
7520 mWindowManager.moveAppToken(lastReparentPos, p);
7521 mWindowManager.setAppGroupId(p, p.task.taskId);
7522 if (VALIDATE_TOKENS) {
7523 mWindowManager.validateAppTokens(mHistory);
7524 }
7525 }
7526 replyChainEnd = -1;
7527
7528 // Now we've moved it in to place... but what if this is
7529 // a singleTop activity and we have put it on top of another
7530 // instance of the same activity? Then we drop the instance
7531 // below so it remains singleTop.
7532 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7533 for (int j=lastReparentPos-1; j>=0; j--) {
7534 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7535 if (p.finishing) {
7536 continue;
7537 }
7538 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7539 if (finishActivityLocked(p, j,
7540 Activity.RESULT_CANCELED, null, "replace")) {
7541 taskTopI--;
7542 lastReparentPos--;
7543 }
7544 }
7545 }
7546 }
7547 }
7548 }
7549
7550 target = below;
7551 targetI = i;
7552 }
7553
7554 return taskTop;
7555 }
7556
7557 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007558 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559 */
7560 public void moveTaskToFront(int task) {
7561 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7562 "moveTaskToFront()");
7563
7564 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007565 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7566 Binder.getCallingUid(), "Task to front")) {
7567 return;
7568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569 final long origId = Binder.clearCallingIdentity();
7570 try {
7571 int N = mRecentTasks.size();
7572 for (int i=0; i<N; i++) {
7573 TaskRecord tr = mRecentTasks.get(i);
7574 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007575 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007576 return;
7577 }
7578 }
7579 for (int i=mHistory.size()-1; i>=0; i--) {
7580 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7581 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007582 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 return;
7584 }
7585 }
7586 } finally {
7587 Binder.restoreCallingIdentity(origId);
7588 }
7589 }
7590 }
7591
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007592 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007593 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007594
7595 final int task = tr.taskId;
7596 int top = mHistory.size()-1;
7597
7598 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7599 // nothing to do!
7600 return;
7601 }
7602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 ArrayList moved = new ArrayList();
7604
7605 // Applying the affinities may have removed entries from the history,
7606 // so get the size again.
7607 top = mHistory.size()-1;
7608 int pos = top;
7609
7610 // Shift all activities with this task up to the top
7611 // of the stack, keeping them in the same internal order.
7612 while (pos >= 0) {
7613 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007614 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007615 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7616 boolean first = true;
7617 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007618 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007619 mHistory.remove(pos);
7620 mHistory.add(top, r);
7621 moved.add(0, r);
7622 top--;
7623 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007624 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 first = false;
7626 }
7627 }
7628 pos--;
7629 }
7630
Joe Onorato8a9b2202010-02-26 18:56:32 -08007631 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007632 "Prepare to front transition: task=" + tr);
7633 if (reason != null &&
7634 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7635 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7636 HistoryRecord r = topRunningActivityLocked(null);
7637 if (r != null) {
7638 mNoAnimActivities.add(r);
7639 }
7640 } else {
7641 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7642 }
7643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007644 mWindowManager.moveAppTokensToTop(moved);
7645 if (VALIDATE_TOKENS) {
7646 mWindowManager.validateAppTokens(mHistory);
7647 }
7648
Josh Bartel7f208742010-02-25 11:01:44 -06007649 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007650 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007651 }
7652
Josh Bartel7f208742010-02-25 11:01:44 -06007653 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007654 resumeTopActivityLocked(null);
7655 }
7656
7657 public void moveTaskToBack(int task) {
7658 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7659 "moveTaskToBack()");
7660
7661 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007662 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7663 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7664 Binder.getCallingUid(), "Task to back")) {
7665 return;
7666 }
7667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007668 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007669 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007670 Binder.restoreCallingIdentity(origId);
7671 }
7672 }
7673
7674 /**
7675 * Moves an activity, and all of the other activities within the same task, to the bottom
7676 * of the history stack. The activity's order within the task is unchanged.
7677 *
7678 * @param token A reference to the activity we wish to move
7679 * @param nonRoot If false then this only works if the activity is the root
7680 * of a task; if true it will work for any activity in a task.
7681 * @return Returns true if the move completed, false if not.
7682 */
7683 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7684 synchronized(this) {
7685 final long origId = Binder.clearCallingIdentity();
7686 int taskId = getTaskForActivityLocked(token, !nonRoot);
7687 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007688 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007689 }
7690 Binder.restoreCallingIdentity(origId);
7691 }
7692 return false;
7693 }
7694
7695 /**
7696 * Worker method for rearranging history stack. Implements the function of moving all
7697 * activities for a specific task (gathering them if disjoint) into a single group at the
7698 * bottom of the stack.
7699 *
7700 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7701 * to premeptively cancel the move.
7702 *
7703 * @param task The taskId to collect and move to the bottom.
7704 * @return Returns true if the move completed, false if not.
7705 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007706 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007707 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007708
7709 // If we have a watcher, preflight the move before committing to it. First check
7710 // for *other* available tasks, but if none are available, then try again allowing the
7711 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007712 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007713 HistoryRecord next = topRunningActivityLocked(null, task);
7714 if (next == null) {
7715 next = topRunningActivityLocked(null, 0);
7716 }
7717 if (next != null) {
7718 // ask watcher if this is allowed
7719 boolean moveOK = true;
7720 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007721 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007722 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007723 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007724 }
7725 if (!moveOK) {
7726 return false;
7727 }
7728 }
7729 }
7730
7731 ArrayList moved = new ArrayList();
7732
Joe Onorato8a9b2202010-02-26 18:56:32 -08007733 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007734 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007735
7736 final int N = mHistory.size();
7737 int bottom = 0;
7738 int pos = 0;
7739
7740 // Shift all activities with this task down to the bottom
7741 // of the stack, keeping them in the same internal order.
7742 while (pos < N) {
7743 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007744 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007745 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7746 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007747 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007748 mHistory.remove(pos);
7749 mHistory.add(bottom, r);
7750 moved.add(r);
7751 bottom++;
7752 }
7753 pos++;
7754 }
7755
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007756 if (reason != null &&
7757 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7758 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7759 HistoryRecord r = topRunningActivityLocked(null);
7760 if (r != null) {
7761 mNoAnimActivities.add(r);
7762 }
7763 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007764 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007766 mWindowManager.moveAppTokensToBottom(moved);
7767 if (VALIDATE_TOKENS) {
7768 mWindowManager.validateAppTokens(mHistory);
7769 }
7770
Josh Bartel7f208742010-02-25 11:01:44 -06007771 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007772 return true;
7773 }
7774
7775 public void moveTaskBackwards(int task) {
7776 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7777 "moveTaskBackwards()");
7778
7779 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007780 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7781 Binder.getCallingUid(), "Task backwards")) {
7782 return;
7783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007784 final long origId = Binder.clearCallingIdentity();
7785 moveTaskBackwardsLocked(task);
7786 Binder.restoreCallingIdentity(origId);
7787 }
7788 }
7789
7790 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007791 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 }
7793
7794 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7795 synchronized(this) {
7796 return getTaskForActivityLocked(token, onlyRoot);
7797 }
7798 }
7799
7800 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7801 final int N = mHistory.size();
7802 TaskRecord lastTask = null;
7803 for (int i=0; i<N; i++) {
7804 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7805 if (r == token) {
7806 if (!onlyRoot || lastTask != r.task) {
7807 return r.task.taskId;
7808 }
7809 return -1;
7810 }
7811 lastTask = r.task;
7812 }
7813
7814 return -1;
7815 }
7816
7817 /**
7818 * Returns the top activity in any existing task matching the given
7819 * Intent. Returns null if no such task is found.
7820 */
7821 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7822 ComponentName cls = intent.getComponent();
7823 if (info.targetActivity != null) {
7824 cls = new ComponentName(info.packageName, info.targetActivity);
7825 }
7826
7827 TaskRecord cp = null;
7828
7829 final int N = mHistory.size();
7830 for (int i=(N-1); i>=0; i--) {
7831 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7832 if (!r.finishing && r.task != cp
7833 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7834 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007835 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007836 // + "/aff=" + r.task.affinity + " to new cls="
7837 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7838 if (r.task.affinity != null) {
7839 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007840 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007841 return r;
7842 }
7843 } else if (r.task.intent != null
7844 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007845 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007846 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007847 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007848 return r;
7849 } else if (r.task.affinityIntent != null
7850 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007851 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007852 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007853 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007854 return r;
7855 }
7856 }
7857 }
7858
7859 return null;
7860 }
7861
7862 /**
7863 * Returns the first activity (starting from the top of the stack) that
7864 * is the same as the given activity. Returns null if no such activity
7865 * is found.
7866 */
7867 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7868 ComponentName cls = intent.getComponent();
7869 if (info.targetActivity != null) {
7870 cls = new ComponentName(info.packageName, info.targetActivity);
7871 }
7872
7873 final int N = mHistory.size();
7874 for (int i=(N-1); i>=0; i--) {
7875 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7876 if (!r.finishing) {
7877 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007878 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007879 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007880 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 return r;
7882 }
7883 }
7884 }
7885
7886 return null;
7887 }
7888
7889 public void finishOtherInstances(IBinder token, ComponentName className) {
7890 synchronized(this) {
7891 final long origId = Binder.clearCallingIdentity();
7892
7893 int N = mHistory.size();
7894 TaskRecord lastTask = null;
7895 for (int i=0; i<N; i++) {
7896 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7897 if (r.realActivity.equals(className)
7898 && r != token && lastTask != r.task) {
7899 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7900 null, "others")) {
7901 i--;
7902 N--;
7903 }
7904 }
7905 lastTask = r.task;
7906 }
7907
7908 Binder.restoreCallingIdentity(origId);
7909 }
7910 }
7911
7912 // =========================================================
7913 // THUMBNAILS
7914 // =========================================================
7915
7916 public void reportThumbnail(IBinder token,
7917 Bitmap thumbnail, CharSequence description) {
7918 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7919 final long origId = Binder.clearCallingIdentity();
7920 sendPendingThumbnail(null, token, thumbnail, description, true);
7921 Binder.restoreCallingIdentity(origId);
7922 }
7923
7924 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7925 Bitmap thumbnail, CharSequence description, boolean always) {
7926 TaskRecord task = null;
7927 ArrayList receivers = null;
7928
7929 //System.out.println("Send pending thumbnail: " + r);
7930
7931 synchronized(this) {
7932 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007933 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007934 if (index < 0) {
7935 return;
7936 }
7937 r = (HistoryRecord)mHistory.get(index);
7938 }
7939 if (thumbnail == null) {
7940 thumbnail = r.thumbnail;
7941 description = r.description;
7942 }
7943 if (thumbnail == null && !always) {
7944 // If there is no thumbnail, and this entry is not actually
7945 // going away, then abort for now and pick up the next
7946 // thumbnail we get.
7947 return;
7948 }
7949 task = r.task;
7950
7951 int N = mPendingThumbnails.size();
7952 int i=0;
7953 while (i<N) {
7954 PendingThumbnailsRecord pr =
7955 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7956 //System.out.println("Looking in " + pr.pendingRecords);
7957 if (pr.pendingRecords.remove(r)) {
7958 if (receivers == null) {
7959 receivers = new ArrayList();
7960 }
7961 receivers.add(pr);
7962 if (pr.pendingRecords.size() == 0) {
7963 pr.finished = true;
7964 mPendingThumbnails.remove(i);
7965 N--;
7966 continue;
7967 }
7968 }
7969 i++;
7970 }
7971 }
7972
7973 if (receivers != null) {
7974 final int N = receivers.size();
7975 for (int i=0; i<N; i++) {
7976 try {
7977 PendingThumbnailsRecord pr =
7978 (PendingThumbnailsRecord)receivers.get(i);
7979 pr.receiver.newThumbnail(
7980 task != null ? task.taskId : -1, thumbnail, description);
7981 if (pr.finished) {
7982 pr.receiver.finished();
7983 }
7984 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007985 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007986 }
7987 }
7988 }
7989 }
7990
7991 // =========================================================
7992 // CONTENT PROVIDERS
7993 // =========================================================
7994
7995 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7996 List providers = null;
7997 try {
7998 providers = ActivityThread.getPackageManager().
7999 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008000 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008001 } catch (RemoteException ex) {
8002 }
8003 if (providers != null) {
8004 final int N = providers.size();
8005 for (int i=0; i<N; i++) {
8006 ProviderInfo cpi =
8007 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008008 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008009 if (cpr == null) {
8010 cpr = new ContentProviderRecord(cpi, app.info);
8011 mProvidersByClass.put(cpi.name, cpr);
8012 }
8013 app.pubProviders.put(cpi.name, cpr);
8014 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008015 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008016 }
8017 }
8018 return providers;
8019 }
8020
8021 private final String checkContentProviderPermissionLocked(
8022 ProviderInfo cpi, ProcessRecord r, int mode) {
8023 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
8024 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
8025 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
8026 cpi.exported ? -1 : cpi.applicationInfo.uid)
8027 == PackageManager.PERMISSION_GRANTED
8028 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8029 return null;
8030 }
8031 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
8032 cpi.exported ? -1 : cpi.applicationInfo.uid)
8033 == PackageManager.PERMISSION_GRANTED) {
8034 return null;
8035 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07008036
8037 PathPermission[] pps = cpi.pathPermissions;
8038 if (pps != null) {
8039 int i = pps.length;
8040 while (i > 0) {
8041 i--;
8042 PathPermission pp = pps[i];
8043 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
8044 cpi.exported ? -1 : cpi.applicationInfo.uid)
8045 == PackageManager.PERMISSION_GRANTED
8046 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8047 return null;
8048 }
8049 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
8050 cpi.exported ? -1 : cpi.applicationInfo.uid)
8051 == PackageManager.PERMISSION_GRANTED) {
8052 return null;
8053 }
8054 }
8055 }
8056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008057 String msg = "Permission Denial: opening provider " + cpi.name
8058 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
8059 + ", uid=" + callingUid + ") requires "
8060 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008061 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008062 return msg;
8063 }
8064
8065 private final ContentProviderHolder getContentProviderImpl(
8066 IApplicationThread caller, String name) {
8067 ContentProviderRecord cpr;
8068 ProviderInfo cpi = null;
8069
8070 synchronized(this) {
8071 ProcessRecord r = null;
8072 if (caller != null) {
8073 r = getRecordForAppLocked(caller);
8074 if (r == null) {
8075 throw new SecurityException(
8076 "Unable to find app for caller " + caller
8077 + " (pid=" + Binder.getCallingPid()
8078 + ") when getting content provider " + name);
8079 }
8080 }
8081
8082 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07008083 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008084 if (cpr != null) {
8085 cpi = cpr.info;
8086 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8087 return new ContentProviderHolder(cpi,
8088 cpi.readPermission != null
8089 ? cpi.readPermission : cpi.writePermission);
8090 }
8091
8092 if (r != null && cpr.canRunHere(r)) {
8093 // This provider has been published or is in the process
8094 // of being published... but it is also allowed to run
8095 // in the caller's process, so don't make a connection
8096 // and just let the caller instantiate its own instance.
8097 if (cpr.provider != null) {
8098 // don't give caller the provider object, it needs
8099 // to make its own.
8100 cpr = new ContentProviderRecord(cpr);
8101 }
8102 return cpr;
8103 }
8104
8105 final long origId = Binder.clearCallingIdentity();
8106
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008107 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008108 // return it right away.
8109 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008110 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008111 "Adding provider requested by "
8112 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008113 + cpr.info.processName);
8114 Integer cnt = r.conProviders.get(cpr);
8115 if (cnt == null) {
8116 r.conProviders.put(cpr, new Integer(1));
8117 } else {
8118 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008120 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008121 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
8122 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07008123 // make sure to count it as being accessed and thus
8124 // back up on the LRU list. This is good because
8125 // content providers are often expensive to start.
8126 updateLruProcessLocked(cpr.app, false, true);
8127 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07008128 } else {
8129 cpr.externals++;
8130 }
8131
8132 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008133 updateOomAdjLocked(cpr.app);
8134 }
8135
8136 Binder.restoreCallingIdentity(origId);
8137
8138 } else {
8139 try {
8140 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008141 resolveContentProvider(name,
8142 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008143 } catch (RemoteException ex) {
8144 }
8145 if (cpi == null) {
8146 return null;
8147 }
8148
8149 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8150 return new ContentProviderHolder(cpi,
8151 cpi.readPermission != null
8152 ? cpi.readPermission : cpi.writePermission);
8153 }
8154
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008155 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
8156 && !cpi.processName.equals("system")) {
8157 // If this content provider does not run in the system
8158 // process, and the system is not yet ready to run other
8159 // processes, then fail fast instead of hanging.
8160 throw new IllegalArgumentException(
8161 "Attempt to launch content provider before system ready");
8162 }
8163
Dianne Hackborn860755f2010-06-03 18:47:52 -07008164 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165 final boolean firstClass = cpr == null;
8166 if (firstClass) {
8167 try {
8168 ApplicationInfo ai =
8169 ActivityThread.getPackageManager().
8170 getApplicationInfo(
8171 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008172 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008174 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 + cpi.name);
8176 return null;
8177 }
8178 cpr = new ContentProviderRecord(cpi, ai);
8179 } catch (RemoteException ex) {
8180 // pm is in same process, this will never happen.
8181 }
8182 }
8183
8184 if (r != null && cpr.canRunHere(r)) {
8185 // If this is a multiprocess provider, then just return its
8186 // info and allow the caller to instantiate it. Only do
8187 // this if the provider is the same user as the caller's
8188 // process, or can run as root (so can be in any process).
8189 return cpr;
8190 }
8191
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008192 if (DEBUG_PROVIDER) {
8193 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08008194 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008195 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008196 }
8197
8198 // This is single process, and our app is now connecting to it.
8199 // See if we are already in the process of launching this
8200 // provider.
8201 final int N = mLaunchingProviders.size();
8202 int i;
8203 for (i=0; i<N; i++) {
8204 if (mLaunchingProviders.get(i) == cpr) {
8205 break;
8206 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008207 }
8208
8209 // If the provider is not already being launched, then get it
8210 // started.
8211 if (i >= N) {
8212 final long origId = Binder.clearCallingIdentity();
8213 ProcessRecord proc = startProcessLocked(cpi.processName,
8214 cpr.appInfo, false, 0, "content provider",
8215 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008216 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008218 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219 + cpi.applicationInfo.packageName + "/"
8220 + cpi.applicationInfo.uid + " for provider "
8221 + name + ": process is bad");
8222 return null;
8223 }
8224 cpr.launchingApp = proc;
8225 mLaunchingProviders.add(cpr);
8226 Binder.restoreCallingIdentity(origId);
8227 }
8228
8229 // Make sure the provider is published (the same provider class
8230 // may be published under multiple names).
8231 if (firstClass) {
8232 mProvidersByClass.put(cpi.name, cpr);
8233 }
8234 mProvidersByName.put(name, cpr);
8235
8236 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008237 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008238 "Adding provider requested by "
8239 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008240 + cpr.info.processName);
8241 Integer cnt = r.conProviders.get(cpr);
8242 if (cnt == null) {
8243 r.conProviders.put(cpr, new Integer(1));
8244 } else {
8245 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8246 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008247 cpr.clients.add(r);
8248 } else {
8249 cpr.externals++;
8250 }
8251 }
8252 }
8253
8254 // Wait for the provider to be published...
8255 synchronized (cpr) {
8256 while (cpr.provider == null) {
8257 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008258 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008259 + cpi.applicationInfo.packageName + "/"
8260 + cpi.applicationInfo.uid + " for provider "
8261 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008262 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008263 cpi.applicationInfo.packageName,
8264 cpi.applicationInfo.uid, name);
8265 return null;
8266 }
8267 try {
8268 cpr.wait();
8269 } catch (InterruptedException ex) {
8270 }
8271 }
8272 }
8273 return cpr;
8274 }
8275
8276 public final ContentProviderHolder getContentProvider(
8277 IApplicationThread caller, String name) {
8278 if (caller == null) {
8279 String msg = "null IApplicationThread when getting content provider "
8280 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008281 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008282 throw new SecurityException(msg);
8283 }
8284
8285 return getContentProviderImpl(caller, name);
8286 }
8287
8288 private ContentProviderHolder getContentProviderExternal(String name) {
8289 return getContentProviderImpl(null, name);
8290 }
8291
8292 /**
8293 * Drop a content provider from a ProcessRecord's bookkeeping
8294 * @param cpr
8295 */
8296 public void removeContentProvider(IApplicationThread caller, String name) {
8297 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008298 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008299 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008300 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008301 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008302 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008303 return;
8304 }
8305 final ProcessRecord r = getRecordForAppLocked(caller);
8306 if (r == null) {
8307 throw new SecurityException(
8308 "Unable to find app for caller " + caller +
8309 " when removing content provider " + name);
8310 }
8311 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008312 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008313 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008314 + r.info.processName + " from process "
8315 + localCpr.appInfo.processName);
8316 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008317 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008318 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008319 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008320 return;
8321 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008322 Integer cnt = r.conProviders.get(localCpr);
8323 if (cnt == null || cnt.intValue() <= 1) {
8324 localCpr.clients.remove(r);
8325 r.conProviders.remove(localCpr);
8326 } else {
8327 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008329 }
8330 updateOomAdjLocked();
8331 }
8332 }
8333
8334 private void removeContentProviderExternal(String name) {
8335 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008336 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008337 if(cpr == null) {
8338 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008339 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008340 return;
8341 }
8342
8343 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008344 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345 localCpr.externals--;
8346 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008347 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008348 }
8349 updateOomAdjLocked();
8350 }
8351 }
8352
8353 public final void publishContentProviders(IApplicationThread caller,
8354 List<ContentProviderHolder> providers) {
8355 if (providers == null) {
8356 return;
8357 }
8358
8359 synchronized(this) {
8360 final ProcessRecord r = getRecordForAppLocked(caller);
8361 if (r == null) {
8362 throw new SecurityException(
8363 "Unable to find app for caller " + caller
8364 + " (pid=" + Binder.getCallingPid()
8365 + ") when publishing content providers");
8366 }
8367
8368 final long origId = Binder.clearCallingIdentity();
8369
8370 final int N = providers.size();
8371 for (int i=0; i<N; i++) {
8372 ContentProviderHolder src = providers.get(i);
8373 if (src == null || src.info == null || src.provider == null) {
8374 continue;
8375 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07008376 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008377 if (dst != null) {
8378 mProvidersByClass.put(dst.info.name, dst);
8379 String names[] = dst.info.authority.split(";");
8380 for (int j = 0; j < names.length; j++) {
8381 mProvidersByName.put(names[j], dst);
8382 }
8383
8384 int NL = mLaunchingProviders.size();
8385 int j;
8386 for (j=0; j<NL; j++) {
8387 if (mLaunchingProviders.get(j) == dst) {
8388 mLaunchingProviders.remove(j);
8389 j--;
8390 NL--;
8391 }
8392 }
8393 synchronized (dst) {
8394 dst.provider = src.provider;
8395 dst.app = r;
8396 dst.notifyAll();
8397 }
8398 updateOomAdjLocked(r);
8399 }
8400 }
8401
8402 Binder.restoreCallingIdentity(origId);
8403 }
8404 }
8405
8406 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008407 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008408 synchronized (mSelf) {
8409 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8410 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008411 if (providers != null) {
8412 for (int i=providers.size()-1; i>=0; i--) {
8413 ProviderInfo pi = (ProviderInfo)providers.get(i);
8414 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8415 Slog.w(TAG, "Not installing system proc provider " + pi.name
8416 + ": not system .apk");
8417 providers.remove(i);
8418 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008419 }
8420 }
8421 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008422 if (providers != null) {
8423 mSystemThread.installSystemProviders(providers);
8424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 }
8426
8427 // =========================================================
8428 // GLOBAL MANAGEMENT
8429 // =========================================================
8430
8431 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8432 ApplicationInfo info, String customProcess) {
8433 String proc = customProcess != null ? customProcess : info.processName;
8434 BatteryStatsImpl.Uid.Proc ps = null;
8435 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8436 synchronized (stats) {
8437 ps = stats.getProcessStatsLocked(info.uid, proc);
8438 }
8439 return new ProcessRecord(ps, thread, info, proc);
8440 }
8441
8442 final ProcessRecord addAppLocked(ApplicationInfo info) {
8443 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8444
8445 if (app == null) {
8446 app = newProcessRecordLocked(null, info, null);
8447 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008448 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008449 }
8450
8451 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8452 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8453 app.persistent = true;
8454 app.maxAdj = CORE_SERVER_ADJ;
8455 }
8456 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8457 mPersistentStartingProcesses.add(app);
8458 startProcessLocked(app, "added application", app.processName);
8459 }
8460
8461 return app;
8462 }
8463
8464 public void unhandledBack() {
8465 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8466 "unhandledBack()");
8467
8468 synchronized(this) {
8469 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008470 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 TAG, "Performing unhandledBack(): stack size = " + count);
8472 if (count > 1) {
8473 final long origId = Binder.clearCallingIdentity();
8474 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8475 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8476 Binder.restoreCallingIdentity(origId);
8477 }
8478 }
8479 }
8480
8481 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8482 String name = uri.getAuthority();
8483 ContentProviderHolder cph = getContentProviderExternal(name);
8484 ParcelFileDescriptor pfd = null;
8485 if (cph != null) {
8486 // We record the binder invoker's uid in thread-local storage before
8487 // going to the content provider to open the file. Later, in the code
8488 // that handles all permissions checks, we look for this uid and use
8489 // that rather than the Activity Manager's own uid. The effect is that
8490 // we do the check against the caller's permissions even though it looks
8491 // to the content provider like the Activity Manager itself is making
8492 // the request.
8493 sCallerIdentity.set(new Identity(
8494 Binder.getCallingPid(), Binder.getCallingUid()));
8495 try {
8496 pfd = cph.provider.openFile(uri, "r");
8497 } catch (FileNotFoundException e) {
8498 // do nothing; pfd will be returned null
8499 } finally {
8500 // Ensure that whatever happens, we clean up the identity state
8501 sCallerIdentity.remove();
8502 }
8503
8504 // We've got the fd now, so we're done with the provider.
8505 removeContentProviderExternal(name);
8506 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008507 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008508 }
8509 return pfd;
8510 }
8511
8512 public void goingToSleep() {
8513 synchronized(this) {
8514 mSleeping = true;
8515 mWindowManager.setEventDispatching(false);
8516
8517 if (mResumedActivity != null) {
8518 pauseIfSleepingLocked();
8519 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008520 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008521 }
8522 }
8523 }
8524
Dianne Hackborn55280a92009-05-07 15:53:46 -07008525 public boolean shutdown(int timeout) {
8526 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8527 != PackageManager.PERMISSION_GRANTED) {
8528 throw new SecurityException("Requires permission "
8529 + android.Manifest.permission.SHUTDOWN);
8530 }
8531
8532 boolean timedout = false;
8533
8534 synchronized(this) {
8535 mShuttingDown = true;
8536 mWindowManager.setEventDispatching(false);
8537
8538 if (mResumedActivity != null) {
8539 pauseIfSleepingLocked();
8540 final long endTime = System.currentTimeMillis() + timeout;
8541 while (mResumedActivity != null || mPausingActivity != null) {
8542 long delay = endTime - System.currentTimeMillis();
8543 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008544 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008545 timedout = true;
8546 break;
8547 }
8548 try {
8549 this.wait();
8550 } catch (InterruptedException e) {
8551 }
8552 }
8553 }
8554 }
8555
8556 mUsageStatsService.shutdown();
8557 mBatteryStatsService.shutdown();
8558
8559 return timedout;
8560 }
8561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008562 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008563 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008564 if (!mGoingToSleep.isHeld()) {
8565 mGoingToSleep.acquire();
8566 if (mLaunchingActivity.isHeld()) {
8567 mLaunchingActivity.release();
8568 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8569 }
8570 }
8571
8572 // If we are not currently pausing an activity, get the current
8573 // one to pause. If we are pausing one, we will just let that stuff
8574 // run and release the wake lock when all done.
8575 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008576 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8577 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008578 startPausingLocked(false, true);
8579 }
8580 }
8581 }
8582
8583 public void wakingUp() {
8584 synchronized(this) {
8585 if (mGoingToSleep.isHeld()) {
8586 mGoingToSleep.release();
8587 }
8588 mWindowManager.setEventDispatching(true);
8589 mSleeping = false;
8590 resumeTopActivityLocked(null);
8591 }
8592 }
8593
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008594 public void stopAppSwitches() {
8595 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8596 != PackageManager.PERMISSION_GRANTED) {
8597 throw new SecurityException("Requires permission "
8598 + android.Manifest.permission.STOP_APP_SWITCHES);
8599 }
8600
8601 synchronized(this) {
8602 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8603 + APP_SWITCH_DELAY_TIME;
8604 mDidAppSwitch = false;
8605 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8606 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8607 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8608 }
8609 }
8610
8611 public void resumeAppSwitches() {
8612 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8613 != PackageManager.PERMISSION_GRANTED) {
8614 throw new SecurityException("Requires permission "
8615 + android.Manifest.permission.STOP_APP_SWITCHES);
8616 }
8617
8618 synchronized(this) {
8619 // Note that we don't execute any pending app switches... we will
8620 // let those wait until either the timeout, or the next start
8621 // activity request.
8622 mAppSwitchesAllowedTime = 0;
8623 }
8624 }
8625
8626 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8627 String name) {
8628 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8629 return true;
8630 }
8631
8632 final int perm = checkComponentPermission(
8633 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8634 callingUid, -1);
8635 if (perm == PackageManager.PERMISSION_GRANTED) {
8636 return true;
8637 }
8638
Joe Onorato8a9b2202010-02-26 18:56:32 -08008639 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008640 return false;
8641 }
8642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643 public void setDebugApp(String packageName, boolean waitForDebugger,
8644 boolean persistent) {
8645 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8646 "setDebugApp()");
8647
8648 // Note that this is not really thread safe if there are multiple
8649 // callers into it at the same time, but that's not a situation we
8650 // care about.
8651 if (persistent) {
8652 final ContentResolver resolver = mContext.getContentResolver();
8653 Settings.System.putString(
8654 resolver, Settings.System.DEBUG_APP,
8655 packageName);
8656 Settings.System.putInt(
8657 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8658 waitForDebugger ? 1 : 0);
8659 }
8660
8661 synchronized (this) {
8662 if (!persistent) {
8663 mOrigDebugApp = mDebugApp;
8664 mOrigWaitForDebugger = mWaitForDebugger;
8665 }
8666 mDebugApp = packageName;
8667 mWaitForDebugger = waitForDebugger;
8668 mDebugTransient = !persistent;
8669 if (packageName != null) {
8670 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008671 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008672 Binder.restoreCallingIdentity(origId);
8673 }
8674 }
8675 }
8676
8677 public void setAlwaysFinish(boolean enabled) {
8678 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8679 "setAlwaysFinish()");
8680
8681 Settings.System.putInt(
8682 mContext.getContentResolver(),
8683 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8684
8685 synchronized (this) {
8686 mAlwaysFinishActivities = enabled;
8687 }
8688 }
8689
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008690 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008691 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008692 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008693 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008694 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008695 }
8696 }
8697
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008698 public boolean isUserAMonkey() {
8699 // For now the fact that there is a controller implies
8700 // we have a monkey.
8701 synchronized (this) {
8702 return mController != null;
8703 }
8704 }
8705
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008706 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008707 synchronized (this) {
8708 mWatchers.register(watcher);
8709 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008710 }
8711
8712 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008713 synchronized (this) {
8714 mWatchers.unregister(watcher);
8715 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008716 }
8717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008718 public final void enterSafeMode() {
8719 synchronized(this) {
8720 // It only makes sense to do this before the system is ready
8721 // and started launching other packages.
8722 if (!mSystemReady) {
8723 try {
8724 ActivityThread.getPackageManager().enterSafeMode();
8725 } catch (RemoteException e) {
8726 }
8727
8728 View v = LayoutInflater.from(mContext).inflate(
8729 com.android.internal.R.layout.safe_mode, null);
8730 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8731 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8732 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8733 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8734 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8735 lp.format = v.getBackground().getOpacity();
8736 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8737 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8738 ((WindowManager)mContext.getSystemService(
8739 Context.WINDOW_SERVICE)).addView(v, lp);
8740 }
8741 }
8742 }
8743
8744 public void noteWakeupAlarm(IIntentSender sender) {
8745 if (!(sender instanceof PendingIntentRecord)) {
8746 return;
8747 }
8748 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8749 synchronized (stats) {
8750 if (mBatteryStatsService.isOnBattery()) {
8751 mBatteryStatsService.enforceCallingPermission();
8752 PendingIntentRecord rec = (PendingIntentRecord)sender;
8753 int MY_UID = Binder.getCallingUid();
8754 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8755 BatteryStatsImpl.Uid.Pkg pkg =
8756 stats.getPackageStatsLocked(uid, rec.key.packageName);
8757 pkg.incWakeupsLocked();
8758 }
8759 }
8760 }
8761
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008762 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008763 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008764 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008765 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008766 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008767 // XXX Note: don't acquire main activity lock here, because the window
8768 // manager calls in with its locks held.
8769
8770 boolean killed = false;
8771 synchronized (mPidsSelfLocked) {
8772 int[] types = new int[pids.length];
8773 int worstType = 0;
8774 for (int i=0; i<pids.length; i++) {
8775 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8776 if (proc != null) {
8777 int type = proc.setAdj;
8778 types[i] = type;
8779 if (type > worstType) {
8780 worstType = type;
8781 }
8782 }
8783 }
8784
8785 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8786 // then constrain it so we will kill all hidden procs.
8787 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8788 worstType = HIDDEN_APP_MIN_ADJ;
8789 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008790 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008791 for (int i=0; i<pids.length; i++) {
8792 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8793 if (proc == null) {
8794 continue;
8795 }
8796 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008797 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008798 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008799 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8800 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008802 proc.killedBackground = true;
8803 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008804 }
8805 }
8806 }
8807 return killed;
8808 }
8809
8810 public void reportPss(IApplicationThread caller, int pss) {
8811 Watchdog.PssRequestor req;
8812 String name;
8813 ProcessRecord callerApp;
8814 synchronized (this) {
8815 if (caller == null) {
8816 return;
8817 }
8818 callerApp = getRecordForAppLocked(caller);
8819 if (callerApp == null) {
8820 return;
8821 }
8822 callerApp.lastPss = pss;
8823 req = callerApp;
8824 name = callerApp.processName;
8825 }
8826 Watchdog.getInstance().reportPss(req, name, pss);
8827 if (!callerApp.persistent) {
8828 removeRequestedPss(callerApp);
8829 }
8830 }
8831
8832 public void requestPss(Runnable completeCallback) {
8833 ArrayList<ProcessRecord> procs;
8834 synchronized (this) {
8835 mRequestPssCallback = completeCallback;
8836 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008837 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8838 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008839 if (!proc.persistent) {
8840 mRequestPssList.add(proc);
8841 }
8842 }
8843 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8844 }
8845
8846 int oldPri = Process.getThreadPriority(Process.myTid());
8847 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8848 for (int i=procs.size()-1; i>=0; i--) {
8849 ProcessRecord proc = procs.get(i);
8850 proc.lastPss = 0;
8851 proc.requestPss();
8852 }
8853 Process.setThreadPriority(oldPri);
8854 }
8855
8856 void removeRequestedPss(ProcessRecord proc) {
8857 Runnable callback = null;
8858 synchronized (this) {
8859 if (mRequestPssList.remove(proc)) {
8860 if (mRequestPssList.size() == 0) {
8861 callback = mRequestPssCallback;
8862 mRequestPssCallback = null;
8863 }
8864 }
8865 }
8866
8867 if (callback != null) {
8868 callback.run();
8869 }
8870 }
8871
8872 public void collectPss(Watchdog.PssStats stats) {
8873 stats.mEmptyPss = 0;
8874 stats.mEmptyCount = 0;
8875 stats.mBackgroundPss = 0;
8876 stats.mBackgroundCount = 0;
8877 stats.mServicePss = 0;
8878 stats.mServiceCount = 0;
8879 stats.mVisiblePss = 0;
8880 stats.mVisibleCount = 0;
8881 stats.mForegroundPss = 0;
8882 stats.mForegroundCount = 0;
8883 stats.mNoPssCount = 0;
8884 synchronized (this) {
8885 int i;
8886 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8887 ? mProcDeaths.length : stats.mProcDeaths.length;
8888 int aggr = 0;
8889 for (i=0; i<NPD; i++) {
8890 aggr += mProcDeaths[i];
8891 stats.mProcDeaths[i] = aggr;
8892 }
8893 while (i<stats.mProcDeaths.length) {
8894 stats.mProcDeaths[i] = 0;
8895 i++;
8896 }
8897
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008898 for (i=mLruProcesses.size()-1; i>=0; i--) {
8899 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008900 if (proc.persistent) {
8901 continue;
8902 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008903 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008904 if (proc.lastPss == 0) {
8905 stats.mNoPssCount++;
8906 continue;
8907 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008908 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8909 if (proc.empty) {
8910 stats.mEmptyPss += proc.lastPss;
8911 stats.mEmptyCount++;
8912 } else {
8913 stats.mBackgroundPss += proc.lastPss;
8914 stats.mBackgroundCount++;
8915 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008916 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8917 stats.mVisiblePss += proc.lastPss;
8918 stats.mVisibleCount++;
8919 } else {
8920 stats.mForegroundPss += proc.lastPss;
8921 stats.mForegroundCount++;
8922 }
8923 }
8924 }
8925 }
8926
8927 public final void startRunning(String pkg, String cls, String action,
8928 String data) {
8929 synchronized(this) {
8930 if (mStartRunning) {
8931 return;
8932 }
8933 mStartRunning = true;
8934 mTopComponent = pkg != null && cls != null
8935 ? new ComponentName(pkg, cls) : null;
8936 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8937 mTopData = data;
8938 if (!mSystemReady) {
8939 return;
8940 }
8941 }
8942
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008943 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008944 }
8945
8946 private void retrieveSettings() {
8947 final ContentResolver resolver = mContext.getContentResolver();
8948 String debugApp = Settings.System.getString(
8949 resolver, Settings.System.DEBUG_APP);
8950 boolean waitForDebugger = Settings.System.getInt(
8951 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8952 boolean alwaysFinishActivities = Settings.System.getInt(
8953 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8954
8955 Configuration configuration = new Configuration();
8956 Settings.System.getConfiguration(resolver, configuration);
8957
8958 synchronized (this) {
8959 mDebugApp = mOrigDebugApp = debugApp;
8960 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8961 mAlwaysFinishActivities = alwaysFinishActivities;
8962 // This happens before any activities are started, so we can
8963 // change mConfiguration in-place.
8964 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008965 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008966 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008967 }
8968 }
8969
8970 public boolean testIsSystemReady() {
8971 // no need to synchronize(this) just to read & return the value
8972 return mSystemReady;
8973 }
8974
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008975 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008976 // In the simulator, startRunning will never have been called, which
8977 // normally sets a few crucial variables. Do it here instead.
8978 if (!Process.supportsProcesses()) {
8979 mStartRunning = true;
8980 mTopAction = Intent.ACTION_MAIN;
8981 }
8982
8983 synchronized(this) {
8984 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008985 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008986 return;
8987 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008988
8989 // Check to see if there are any update receivers to run.
8990 if (!mDidUpdate) {
8991 if (mWaitingUpdate) {
8992 return;
8993 }
8994 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8995 List<ResolveInfo> ris = null;
8996 try {
8997 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8998 intent, null, 0);
8999 } catch (RemoteException e) {
9000 }
9001 if (ris != null) {
9002 for (int i=ris.size()-1; i>=0; i--) {
9003 if ((ris.get(i).activityInfo.applicationInfo.flags
9004 &ApplicationInfo.FLAG_SYSTEM) == 0) {
9005 ris.remove(i);
9006 }
9007 }
9008 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
9009 for (int i=0; i<ris.size(); i++) {
9010 ActivityInfo ai = ris.get(i).activityInfo;
9011 intent.setComponent(new ComponentName(ai.packageName, ai.name));
9012 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08009013 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009014 finisher = new IIntentReceiver.Stub() {
9015 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07009016 String data, Bundle extras, boolean ordered,
9017 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009018 throws RemoteException {
9019 synchronized (ActivityManagerService.this) {
9020 mDidUpdate = true;
9021 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009022 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009023 }
9024 };
9025 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009026 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009027 broadcastIntentLocked(null, null, intent, null, finisher,
9028 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08009029 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009030 mWaitingUpdate = true;
9031 }
9032 }
9033 }
9034 if (mWaitingUpdate) {
9035 return;
9036 }
9037 mDidUpdate = true;
9038 }
9039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009040 mSystemReady = true;
9041 if (!mStartRunning) {
9042 return;
9043 }
9044 }
9045
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009046 ArrayList<ProcessRecord> procsToKill = null;
9047 synchronized(mPidsSelfLocked) {
9048 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
9049 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
9050 if (!isAllowedWhileBooting(proc.info)){
9051 if (procsToKill == null) {
9052 procsToKill = new ArrayList<ProcessRecord>();
9053 }
9054 procsToKill.add(proc);
9055 }
9056 }
9057 }
9058
9059 if (procsToKill != null) {
9060 synchronized(this) {
9061 for (int i=procsToKill.size()-1; i>=0; i--) {
9062 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009063 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009064 removeProcessLocked(proc, true);
9065 }
9066 }
9067 }
9068
Joe Onorato8a9b2202010-02-26 18:56:32 -08009069 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009070 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009071 SystemClock.uptimeMillis());
9072
9073 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009074 // Make sure we have no pre-ready processes sitting around.
9075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009076 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
9077 ResolveInfo ri = mContext.getPackageManager()
9078 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07009079 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009080 CharSequence errorMsg = null;
9081 if (ri != null) {
9082 ActivityInfo ai = ri.activityInfo;
9083 ApplicationInfo app = ai.applicationInfo;
9084 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
9085 mTopAction = Intent.ACTION_FACTORY_TEST;
9086 mTopData = null;
9087 mTopComponent = new ComponentName(app.packageName,
9088 ai.name);
9089 } else {
9090 errorMsg = mContext.getResources().getText(
9091 com.android.internal.R.string.factorytest_not_system);
9092 }
9093 } else {
9094 errorMsg = mContext.getResources().getText(
9095 com.android.internal.R.string.factorytest_no_action);
9096 }
9097 if (errorMsg != null) {
9098 mTopAction = null;
9099 mTopData = null;
9100 mTopComponent = null;
9101 Message msg = Message.obtain();
9102 msg.what = SHOW_FACTORY_ERROR_MSG;
9103 msg.getData().putCharSequence("msg", errorMsg);
9104 mHandler.sendMessage(msg);
9105 }
9106 }
9107 }
9108
9109 retrieveSettings();
9110
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009111 if (goingCallback != null) goingCallback.run();
9112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009113 synchronized (this) {
9114 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
9115 try {
9116 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009117 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009118 if (apps != null) {
9119 int N = apps.size();
9120 int i;
9121 for (i=0; i<N; i++) {
9122 ApplicationInfo info
9123 = (ApplicationInfo)apps.get(i);
9124 if (info != null &&
9125 !info.packageName.equals("android")) {
9126 addAppLocked(info);
9127 }
9128 }
9129 }
9130 } catch (RemoteException ex) {
9131 // pm is in same process, this will never happen.
9132 }
9133 }
9134
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009135 // Start up initial activity.
9136 mBooting = true;
9137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009138 try {
9139 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
9140 Message msg = Message.obtain();
9141 msg.what = SHOW_UID_ERROR_MSG;
9142 mHandler.sendMessage(msg);
9143 }
9144 } catch (RemoteException e) {
9145 }
9146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009147 resumeTopActivityLocked(null);
9148 }
9149 }
9150
Dan Egnorb7f03672009-12-09 16:22:32 -08009151 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009152 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009153 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009154 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009155 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009156 startAppProblemLocked(app);
9157 app.stopFreezingAllLocked();
9158 return handleAppCrashLocked(app);
9159 }
9160
Dan Egnorb7f03672009-12-09 16:22:32 -08009161 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009162 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009163 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009164 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009165 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
9166 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009167 startAppProblemLocked(app);
9168 app.stopFreezingAllLocked();
9169 }
9170
9171 /**
9172 * Generate a process error record, suitable for attachment to a ProcessRecord.
9173 *
9174 * @param app The ProcessRecord in which the error occurred.
9175 * @param condition Crashing, Application Not Responding, etc. Values are defined in
9176 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08009177 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009178 * @param shortMsg Short message describing the crash.
9179 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08009180 * @param stackTrace Full crash stack trace, may be null.
9181 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182 * @return Returns a fully-formed AppErrorStateInfo record.
9183 */
9184 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009185 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009186 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08009187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009188 report.condition = condition;
9189 report.processName = app.processName;
9190 report.pid = app.pid;
9191 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08009192 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009193 report.shortMsg = shortMsg;
9194 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08009195 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009196
9197 return report;
9198 }
9199
Dan Egnor42471dd2010-01-07 17:25:22 -08009200 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009201 synchronized (this) {
9202 app.crashing = false;
9203 app.crashingReport = null;
9204 app.notResponding = false;
9205 app.notRespondingReport = null;
9206 if (app.anrDialog == fromDialog) {
9207 app.anrDialog = null;
9208 }
9209 if (app.waitDialog == fromDialog) {
9210 app.waitDialog = null;
9211 }
9212 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009213 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07009214 Slog.i(ActivityManagerService.TAG, "Killing "
9215 + app.processName + " (pid=" + app.pid + "): user's request");
9216 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
9217 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009218 Process.killProcess(app.pid);
9219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009220 }
9221 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009222
Dan Egnorb7f03672009-12-09 16:22:32 -08009223 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009224 long now = SystemClock.uptimeMillis();
9225
9226 Long crashTime = mProcessCrashTimes.get(app.info.processName,
9227 app.info.uid);
9228 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
9229 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08009230 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009232 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009233 app.info.processName, app.info.uid);
9234 killServicesLocked(app, false);
9235 for (int i=mHistory.size()-1; i>=0; i--) {
9236 HistoryRecord r = (HistoryRecord)mHistory.get(i);
9237 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009238 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009239 + r.intent.getComponent().flattenToShortString());
9240 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
9241 }
9242 }
9243 if (!app.persistent) {
9244 // We don't want to start this process again until the user
9245 // explicitly does so... but for persistent process, we really
9246 // need to keep it running. If a persistent process is actually
9247 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08009248 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009249 app.info.processName);
9250 mBadProcesses.put(app.info.processName, app.info.uid, now);
9251 app.bad = true;
9252 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
9253 app.removed = true;
9254 removeProcessLocked(app, false);
9255 return false;
9256 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009257 } else {
9258 HistoryRecord r = topRunningActivityLocked(null);
9259 if (r.app == app) {
9260 // If the top running activity is from this crashing
9261 // process, then terminate it to avoid getting in a loop.
9262 Slog.w(TAG, " Force finishing activity "
9263 + r.intent.getComponent().flattenToShortString());
9264 int index = indexOfTokenLocked(r);
9265 finishActivityLocked(r, index,
9266 Activity.RESULT_CANCELED, null, "crashed");
9267 // Also terminate an activities below it that aren't yet
9268 // stopped, to avoid a situation where one will get
9269 // re-start our crashing activity once it gets resumed again.
9270 index--;
9271 if (index >= 0) {
9272 r = (HistoryRecord)mHistory.get(index);
9273 if (r.state == ActivityState.RESUMED
9274 || r.state == ActivityState.PAUSING
9275 || r.state == ActivityState.PAUSED) {
9276 if (!r.isHomeActivity) {
9277 Slog.w(TAG, " Force finishing activity "
9278 + r.intent.getComponent().flattenToShortString());
9279 finishActivityLocked(r, index,
9280 Activity.RESULT_CANCELED, null, "crashed");
9281 }
9282 }
9283 }
9284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285 }
9286
9287 // Bump up the crash count of any services currently running in the proc.
9288 if (app.services.size() != 0) {
9289 // Any services running in the application need to be placed
9290 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009291 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009292 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009293 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009294 sr.crashCount++;
9295 }
9296 }
9297
9298 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
9299 return true;
9300 }
9301
9302 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009303 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9304 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009305 skipCurrentReceiverLocked(app);
9306 }
9307
9308 void skipCurrentReceiverLocked(ProcessRecord app) {
9309 boolean reschedule = false;
9310 BroadcastRecord r = app.curReceiver;
9311 if (r != null) {
9312 // The current broadcast is waiting for this app's receiver
9313 // to be finished. Looks like that's not going to happen, so
9314 // let the broadcast continue.
9315 logBroadcastReceiverDiscard(r);
9316 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9317 r.resultExtras, r.resultAbort, true);
9318 reschedule = true;
9319 }
9320 r = mPendingBroadcast;
9321 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009322 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009323 "skip & discard pending app " + r);
9324 logBroadcastReceiverDiscard(r);
9325 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9326 r.resultExtras, r.resultAbort, true);
9327 reschedule = true;
9328 }
9329 if (reschedule) {
9330 scheduleBroadcastsLocked();
9331 }
9332 }
9333
Dan Egnor60d87622009-12-16 16:32:58 -08009334 /**
9335 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9336 * The application process will exit immediately after this call returns.
9337 * @param app object of the crashing app, null for the system server
9338 * @param crashInfo describing the exception
9339 */
9340 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9341 ProcessRecord r = findAppProcess(app);
9342
9343 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9344 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009345 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009346 crashInfo.exceptionClassName,
9347 crashInfo.exceptionMessage,
9348 crashInfo.throwFileName,
9349 crashInfo.throwLineNumber);
9350
Dan Egnor42471dd2010-01-07 17:25:22 -08009351 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009352
9353 crashApplication(r, crashInfo);
9354 }
9355
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009356 public void handleApplicationStrictModeViolation(
9357 IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9358 ProcessRecord r = findAppProcess(app);
9359 // TODO: implement
9360 Log.w(TAG, "handleApplicationStrictModeViolation.");
9361
9362 AppErrorResult result = new AppErrorResult();
9363 synchronized (this) {
9364 final long origId = Binder.clearCallingIdentity();
9365
9366 Message msg = Message.obtain();
9367 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
9368 HashMap<String, Object> data = new HashMap<String, Object>();
9369 data.put("result", result);
9370 data.put("app", r);
9371 msg.obj = data;
9372 mHandler.sendMessage(msg);
9373
9374 Binder.restoreCallingIdentity(origId);
9375 }
9376 int res = result.get();
9377 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
9378 }
9379
Dan Egnor60d87622009-12-16 16:32:58 -08009380 /**
9381 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9382 * @param app object of the crashing app, null for the system server
9383 * @param tag reported by the caller
9384 * @param crashInfo describing the context of the error
9385 * @return true if the process should exit immediately (WTF is fatal)
9386 */
9387 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009388 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009389 ProcessRecord r = findAppProcess(app);
9390
9391 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9392 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009393 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009394 tag, crashInfo.exceptionMessage);
9395
Dan Egnor42471dd2010-01-07 17:25:22 -08009396 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009397
Doug Zongker43866e02010-01-07 12:09:54 -08009398 if (Settings.Secure.getInt(mContext.getContentResolver(),
9399 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009400 crashApplication(r, crashInfo);
9401 return true;
9402 } else {
9403 return false;
9404 }
9405 }
9406
9407 /**
9408 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9409 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9410 */
9411 private ProcessRecord findAppProcess(IBinder app) {
9412 if (app == null) {
9413 return null;
9414 }
9415
9416 synchronized (this) {
9417 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9418 final int NA = apps.size();
9419 for (int ia=0; ia<NA; ia++) {
9420 ProcessRecord p = apps.valueAt(ia);
9421 if (p.thread != null && p.thread.asBinder() == app) {
9422 return p;
9423 }
9424 }
9425 }
9426
Joe Onorato8a9b2202010-02-26 18:56:32 -08009427 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009428 return null;
9429 }
9430 }
9431
9432 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009433 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009434 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009435 * @param process which caused the error, null means the system server
9436 * @param activity which triggered the error, null if unknown
9437 * @param parent activity related to the error, null if unknown
9438 * @param subject line related to the error, null if absent
9439 * @param report in long form describing the error, null if absent
9440 * @param logFile to include in the report, null if none
9441 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009442 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009443 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009444 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9445 final String report, final File logFile,
9446 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009447 // NOTE -- this must never acquire the ActivityManagerService lock,
9448 // otherwise the watchdog may be prevented from resetting the system.
9449
Dan Egnora455d192010-03-12 08:52:28 -08009450 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009451 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009452 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009453 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009454 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009455 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009456 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009457 }
9458
Dan Egnora455d192010-03-12 08:52:28 -08009459 final String dropboxTag = prefix + eventType;
9460 final DropBoxManager dbox = (DropBoxManager)
9461 mContext.getSystemService(Context.DROPBOX_SERVICE);
9462
9463 // Exit early if the dropbox isn't configured to accept this report type.
9464 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9465
9466 final StringBuilder sb = new StringBuilder(1024);
9467 if (process == null || process.pid == MY_PID) {
9468 sb.append("Process: system_server\n");
9469 } else {
9470 sb.append("Process: ").append(process.processName).append("\n");
9471 }
9472 if (process != null) {
9473 int flags = process.info.flags;
9474 IPackageManager pm = ActivityThread.getPackageManager();
9475 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9476 for (String pkg : process.pkgList) {
9477 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009478 try {
Dan Egnora455d192010-03-12 08:52:28 -08009479 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9480 if (pi != null) {
9481 sb.append(" v").append(pi.versionCode);
9482 if (pi.versionName != null) {
9483 sb.append(" (").append(pi.versionName).append(")");
9484 }
9485 }
9486 } catch (RemoteException e) {
9487 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009488 }
Dan Egnora455d192010-03-12 08:52:28 -08009489 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009490 }
Dan Egnora455d192010-03-12 08:52:28 -08009491 }
9492 if (activity != null) {
9493 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9494 }
9495 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9496 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9497 }
9498 if (parent != null && parent != activity) {
9499 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9500 }
9501 if (subject != null) {
9502 sb.append("Subject: ").append(subject).append("\n");
9503 }
9504 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9505 sb.append("\n");
9506
9507 // Do the rest in a worker thread to avoid blocking the caller on I/O
9508 // (After this point, we shouldn't access AMS internal data structures.)
9509 Thread worker = new Thread("Error dump: " + dropboxTag) {
9510 @Override
9511 public void run() {
9512 if (report != null) {
9513 sb.append(report);
9514 }
9515 if (logFile != null) {
9516 try {
9517 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9518 } catch (IOException e) {
9519 Slog.e(TAG, "Error reading " + logFile, e);
9520 }
9521 }
9522 if (crashInfo != null && crashInfo.stackTrace != null) {
9523 sb.append(crashInfo.stackTrace);
9524 }
9525
9526 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9527 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9528 if (lines > 0) {
9529 sb.append("\n");
9530
9531 // Merge several logcat streams, and take the last N lines
9532 InputStreamReader input = null;
9533 try {
9534 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9535 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9536 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9537
9538 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9539 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9540 input = new InputStreamReader(logcat.getInputStream());
9541
9542 int num;
9543 char[] buf = new char[8192];
9544 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9545 } catch (IOException e) {
9546 Slog.e(TAG, "Error running logcat", e);
9547 } finally {
9548 if (input != null) try { input.close(); } catch (IOException e) {}
9549 }
9550 }
9551
9552 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009553 }
Dan Egnora455d192010-03-12 08:52:28 -08009554 };
9555
9556 if (process == null || process.pid == MY_PID) {
9557 worker.run(); // We may be about to die -- need to run this synchronously
9558 } else {
9559 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009560 }
9561 }
9562
9563 /**
9564 * Bring up the "unexpected error" dialog box for a crashing app.
9565 * Deal with edge cases (intercepts from instrumented applications,
9566 * ActivityController, error intent receivers, that sort of thing).
9567 * @param r the application crashing
9568 * @param crashInfo describing the failure
9569 */
9570 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009571 long timeMillis = System.currentTimeMillis();
9572 String shortMsg = crashInfo.exceptionClassName;
9573 String longMsg = crashInfo.exceptionMessage;
9574 String stackTrace = crashInfo.stackTrace;
9575 if (shortMsg != null && longMsg != null) {
9576 longMsg = shortMsg + ": " + longMsg;
9577 } else if (shortMsg != null) {
9578 longMsg = shortMsg;
9579 }
9580
Dan Egnor60d87622009-12-16 16:32:58 -08009581 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009582 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009583 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009584 try {
9585 String name = r != null ? r.processName : null;
9586 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009587 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009588 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009589 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009590 + " at watcher's request");
9591 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009592 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009593 }
9594 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009595 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009596 }
9597 }
9598
9599 final long origId = Binder.clearCallingIdentity();
9600
9601 // If this process is running instrumentation, finish it.
9602 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009603 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009604 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009605 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9606 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009607 Bundle info = new Bundle();
9608 info.putString("shortMsg", shortMsg);
9609 info.putString("longMsg", longMsg);
9610 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9611 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009612 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009613 }
9614
Dan Egnor60d87622009-12-16 16:32:58 -08009615 // If we can't identify the process or it's already exceeded its crash quota,
9616 // quit right away without showing a crash dialog.
9617 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009618 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009619 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009620 }
9621
9622 Message msg = Message.obtain();
9623 msg.what = SHOW_ERROR_MSG;
9624 HashMap data = new HashMap();
9625 data.put("result", result);
9626 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009627 msg.obj = data;
9628 mHandler.sendMessage(msg);
9629
9630 Binder.restoreCallingIdentity(origId);
9631 }
9632
9633 int res = result.get();
9634
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009635 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009636 synchronized (this) {
9637 if (r != null) {
9638 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9639 SystemClock.uptimeMillis());
9640 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009641 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009642 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009643 }
9644 }
9645
9646 if (appErrorIntent != null) {
9647 try {
9648 mContext.startActivity(appErrorIntent);
9649 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009650 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009653 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009654
9655 Intent createAppErrorIntentLocked(ProcessRecord r,
9656 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9657 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009658 if (report == null) {
9659 return null;
9660 }
9661 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9662 result.setComponent(r.errorReportReceiver);
9663 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9664 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9665 return result;
9666 }
9667
Dan Egnorb7f03672009-12-09 16:22:32 -08009668 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9669 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009670 if (r.errorReportReceiver == null) {
9671 return null;
9672 }
9673
9674 if (!r.crashing && !r.notResponding) {
9675 return null;
9676 }
9677
Dan Egnorb7f03672009-12-09 16:22:32 -08009678 ApplicationErrorReport report = new ApplicationErrorReport();
9679 report.packageName = r.info.packageName;
9680 report.installerPackageName = r.errorReportReceiver.getPackageName();
9681 report.processName = r.processName;
9682 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009683 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009684
Dan Egnorb7f03672009-12-09 16:22:32 -08009685 if (r.crashing) {
9686 report.type = ApplicationErrorReport.TYPE_CRASH;
9687 report.crashInfo = crashInfo;
9688 } else if (r.notResponding) {
9689 report.type = ApplicationErrorReport.TYPE_ANR;
9690 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009691
Dan Egnorb7f03672009-12-09 16:22:32 -08009692 report.anrInfo.activity = r.notRespondingReport.tag;
9693 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9694 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009695 }
9696
Dan Egnorb7f03672009-12-09 16:22:32 -08009697 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009698 }
9699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9701 // assume our apps are happy - lazy create the list
9702 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9703
9704 synchronized (this) {
9705
9706 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009707 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9708 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009709 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9710 // This one's in trouble, so we'll generate a report for it
9711 // crashes are higher priority (in case there's a crash *and* an anr)
9712 ActivityManager.ProcessErrorStateInfo report = null;
9713 if (app.crashing) {
9714 report = app.crashingReport;
9715 } else if (app.notResponding) {
9716 report = app.notRespondingReport;
9717 }
9718
9719 if (report != null) {
9720 if (errList == null) {
9721 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9722 }
9723 errList.add(report);
9724 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009725 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009726 " crashing = " + app.crashing +
9727 " notResponding = " + app.notResponding);
9728 }
9729 }
9730 }
9731 }
9732
9733 return errList;
9734 }
9735
9736 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9737 // Lazy instantiation of list
9738 List<ActivityManager.RunningAppProcessInfo> runList = null;
9739 synchronized (this) {
9740 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009741 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9742 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009743 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9744 // Generate process state info for running application
9745 ActivityManager.RunningAppProcessInfo currApp =
9746 new ActivityManager.RunningAppProcessInfo(app.processName,
9747 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009748 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009749 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009750 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009751 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9752 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9753 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009754 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9755 } else if (adj >= HOME_APP_ADJ) {
9756 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9757 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009758 } else if (adj >= SECONDARY_SERVER_ADJ) {
9759 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07009760 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
9761 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
9762 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
9763 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009764 } else if (adj >= VISIBLE_APP_ADJ) {
9765 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9766 } else {
9767 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9768 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009769 currApp.importanceReasonCode = app.adjTypeCode;
9770 if (app.adjSource instanceof ProcessRecord) {
9771 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9772 } else if (app.adjSource instanceof HistoryRecord) {
9773 HistoryRecord r = (HistoryRecord)app.adjSource;
9774 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9775 }
9776 if (app.adjTarget instanceof ComponentName) {
9777 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9778 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009779 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780 // + " lru=" + currApp.lru);
9781 if (runList == null) {
9782 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9783 }
9784 runList.add(currApp);
9785 }
9786 }
9787 }
9788 return runList;
9789 }
9790
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009791 public List<ApplicationInfo> getRunningExternalApplications() {
9792 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9793 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9794 if (runningApps != null && runningApps.size() > 0) {
9795 Set<String> extList = new HashSet<String>();
9796 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9797 if (app.pkgList != null) {
9798 for (String pkg : app.pkgList) {
9799 extList.add(pkg);
9800 }
9801 }
9802 }
9803 IPackageManager pm = ActivityThread.getPackageManager();
9804 for (String pkg : extList) {
9805 try {
9806 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9807 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9808 retList.add(info);
9809 }
9810 } catch (RemoteException e) {
9811 }
9812 }
9813 }
9814 return retList;
9815 }
9816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009817 @Override
9818 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009819 if (checkCallingPermission(android.Manifest.permission.DUMP)
9820 != PackageManager.PERMISSION_GRANTED) {
9821 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9822 + Binder.getCallingPid()
9823 + ", uid=" + Binder.getCallingUid()
9824 + " without permission "
9825 + android.Manifest.permission.DUMP);
9826 return;
9827 }
9828
9829 boolean dumpAll = false;
9830
9831 int opti = 0;
9832 while (opti < args.length) {
9833 String opt = args[opti];
9834 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9835 break;
9836 }
9837 opti++;
9838 if ("-a".equals(opt)) {
9839 dumpAll = true;
9840 } else if ("-h".equals(opt)) {
9841 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009842 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009843 pw.println(" cmd may be one of:");
9844 pw.println(" activities: activity stack state");
9845 pw.println(" broadcasts: broadcast state");
9846 pw.println(" intents: pending intent state");
9847 pw.println(" processes: process state");
9848 pw.println(" providers: content provider state");
9849 pw.println(" services: service state");
9850 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009851 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009852 } else {
9853 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009854 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009855 }
9856
9857 // Is the caller requesting to dump a particular piece of data?
9858 if (opti < args.length) {
9859 String cmd = args[opti];
9860 opti++;
9861 if ("activities".equals(cmd) || "a".equals(cmd)) {
9862 synchronized (this) {
9863 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009864 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009865 return;
9866 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9867 synchronized (this) {
9868 dumpBroadcastsLocked(fd, pw, args, opti, true);
9869 }
9870 return;
9871 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9872 synchronized (this) {
9873 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9874 }
9875 return;
9876 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9877 synchronized (this) {
9878 dumpProcessesLocked(fd, pw, args, opti, true);
9879 }
9880 return;
9881 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9882 synchronized (this) {
9883 dumpProvidersLocked(fd, pw, args, opti, true);
9884 }
9885 return;
9886 } else if ("service".equals(cmd)) {
9887 dumpService(fd, pw, args, opti, true);
9888 return;
9889 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9890 synchronized (this) {
9891 dumpServicesLocked(fd, pw, args, opti, true);
9892 }
9893 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009894 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009895 }
9896
9897 // No piece of data specified, dump everything.
9898 synchronized (this) {
9899 boolean needSep;
9900 if (dumpAll) {
9901 pw.println("Providers in Current Activity Manager State:");
9902 }
9903 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9904 if (needSep) {
9905 pw.println(" ");
9906 }
9907 if (dumpAll) {
9908 pw.println("-------------------------------------------------------------------------------");
9909 pw.println("Broadcasts in Current Activity Manager State:");
9910 }
9911 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9912 if (needSep) {
9913 pw.println(" ");
9914 }
9915 if (dumpAll) {
9916 pw.println("-------------------------------------------------------------------------------");
9917 pw.println("Services in Current Activity Manager State:");
9918 }
9919 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9920 if (needSep) {
9921 pw.println(" ");
9922 }
9923 if (dumpAll) {
9924 pw.println("-------------------------------------------------------------------------------");
9925 pw.println("PendingIntents in Current Activity Manager State:");
9926 }
9927 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9928 if (needSep) {
9929 pw.println(" ");
9930 }
9931 if (dumpAll) {
9932 pw.println("-------------------------------------------------------------------------------");
9933 pw.println("Activities in Current Activity Manager State:");
9934 }
9935 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9936 if (needSep) {
9937 pw.println(" ");
9938 }
9939 if (dumpAll) {
9940 pw.println("-------------------------------------------------------------------------------");
9941 pw.println("Processes in Current Activity Manager State:");
9942 }
9943 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9944 }
9945 }
9946
9947 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9948 int opti, boolean dumpAll, boolean needHeader) {
9949 if (needHeader) {
9950 pw.println(" Activity stack:");
9951 }
9952 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9953 pw.println(" ");
9954 pw.println(" Running activities (most recent first):");
9955 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9956 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009957 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009958 pw.println(" Activities waiting for another to become visible:");
9959 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9960 }
9961 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009963 pw.println(" Activities waiting to stop:");
9964 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9965 }
9966 if (mFinishingActivities.size() > 0) {
9967 pw.println(" ");
9968 pw.println(" Activities waiting to finish:");
9969 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009972 pw.println(" ");
9973 pw.println(" mPausingActivity: " + mPausingActivity);
9974 pw.println(" mResumedActivity: " + mResumedActivity);
9975 pw.println(" mFocusedActivity: " + mFocusedActivity);
9976 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009977
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009978 if (dumpAll && mRecentTasks.size() > 0) {
9979 pw.println(" ");
9980 pw.println("Recent tasks in Current Activity Manager State:");
9981
9982 final int N = mRecentTasks.size();
9983 for (int i=0; i<N; i++) {
9984 TaskRecord tr = mRecentTasks.get(i);
9985 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9986 pw.println(tr);
9987 mRecentTasks.get(i).dump(pw, " ");
9988 }
9989 }
9990
9991 pw.println(" ");
9992 pw.println(" mCurTask: " + mCurTask);
9993
9994 return true;
9995 }
9996
9997 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9998 int opti, boolean dumpAll) {
9999 boolean needSep = false;
10000 int numPers = 0;
10001
10002 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010003 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
10004 final int NA = procs.size();
10005 for (int ia=0; ia<NA; ia++) {
10006 if (!needSep) {
10007 pw.println(" All known processes:");
10008 needSep = true;
10009 }
10010 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010011 pw.print(r.persistent ? " *PERS*" : " *APP*");
10012 pw.print(" UID "); pw.print(procs.keyAt(ia));
10013 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010014 r.dump(pw, " ");
10015 if (r.persistent) {
10016 numPers++;
10017 }
10018 }
10019 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010020 }
10021
10022 if (mLruProcesses.size() > 0) {
10023 if (needSep) pw.println(" ");
10024 needSep = true;
10025 pw.println(" Running processes (most recent first):");
10026 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010027 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010028 needSep = true;
10029 }
10030
10031 synchronized (mPidsSelfLocked) {
10032 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010033 if (needSep) pw.println(" ");
10034 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010035 pw.println(" PID mappings:");
10036 for (int i=0; i<mPidsSelfLocked.size(); i++) {
10037 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
10038 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010039 }
10040 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010041 }
10042
10043 if (mForegroundProcesses.size() > 0) {
10044 if (needSep) pw.println(" ");
10045 needSep = true;
10046 pw.println(" Foreground Processes:");
10047 for (int i=0; i<mForegroundProcesses.size(); i++) {
10048 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
10049 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010050 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010051 }
10052
10053 if (mPersistentStartingProcesses.size() > 0) {
10054 if (needSep) pw.println(" ");
10055 needSep = true;
10056 pw.println(" Persisent processes that are starting:");
10057 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
10058 "Starting Norm", "Restarting PERS", false);
10059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010060
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010061 if (mStartingProcesses.size() > 0) {
10062 if (needSep) pw.println(" ");
10063 needSep = true;
10064 pw.println(" Processes that are starting:");
10065 dumpProcessList(pw, this, mStartingProcesses, " ",
10066 "Starting Norm", "Starting PERS", false);
10067 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010068
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010069 if (mRemovedProcesses.size() > 0) {
10070 if (needSep) pw.println(" ");
10071 needSep = true;
10072 pw.println(" Processes that are being removed:");
10073 dumpProcessList(pw, this, mRemovedProcesses, " ",
10074 "Removed Norm", "Removed PERS", false);
10075 }
10076
10077 if (mProcessesOnHold.size() > 0) {
10078 if (needSep) pw.println(" ");
10079 needSep = true;
10080 pw.println(" Processes that are on old until the system is ready:");
10081 dumpProcessList(pw, this, mProcessesOnHold, " ",
10082 "OnHold Norm", "OnHold PERS", false);
10083 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010084
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010085 if (mProcessesToGc.size() > 0) {
10086 if (needSep) pw.println(" ");
10087 needSep = true;
10088 pw.println(" Processes that are waiting to GC:");
10089 long now = SystemClock.uptimeMillis();
10090 for (int i=0; i<mProcessesToGc.size(); i++) {
10091 ProcessRecord proc = mProcessesToGc.get(i);
10092 pw.print(" Process "); pw.println(proc);
10093 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
10094 pw.print(", last gced=");
10095 pw.print(now-proc.lastRequestedGc);
10096 pw.print(" ms ago, last lowMem=");
10097 pw.print(now-proc.lastLowMemory);
10098 pw.println(" ms ago");
10099
10100 }
10101 }
10102
10103 if (mProcessCrashTimes.getMap().size() > 0) {
10104 if (needSep) pw.println(" ");
10105 needSep = true;
10106 pw.println(" Time since processes crashed:");
10107 long now = SystemClock.uptimeMillis();
10108 for (Map.Entry<String, SparseArray<Long>> procs
10109 : mProcessCrashTimes.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(" Process "); pw.print(procs.getKey());
10114 pw.print(" uid "); pw.print(uids.keyAt(i));
10115 pw.print(": last crashed ");
10116 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010117 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010118 }
10119 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010121
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010122 if (mBadProcesses.getMap().size() > 0) {
10123 if (needSep) pw.println(" ");
10124 needSep = true;
10125 pw.println(" Bad processes:");
10126 for (Map.Entry<String, SparseArray<Long>> procs
10127 : mBadProcesses.getMap().entrySet()) {
10128 SparseArray<Long> uids = procs.getValue();
10129 final int N = uids.size();
10130 for (int i=0; i<N; i++) {
10131 pw.print(" Bad process "); pw.print(procs.getKey());
10132 pw.print(" uid "); pw.print(uids.keyAt(i));
10133 pw.print(": crashed at time ");
10134 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010135 }
10136 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010137 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010138
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010139 pw.println(" ");
10140 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010141 if (mHeavyWeightProcess != null) {
10142 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
10143 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010144 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -070010145 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010146 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
10147 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
10148 || mOrigWaitForDebugger) {
10149 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
10150 + " mDebugTransient=" + mDebugTransient
10151 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
10152 }
10153 if (mAlwaysFinishActivities || mController != null) {
10154 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
10155 + " mController=" + mController);
10156 }
10157 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010158 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010159 pw.println(" mStartRunning=" + mStartRunning
10160 + " mSystemReady=" + mSystemReady
10161 + " mBooting=" + mBooting
10162 + " mBooted=" + mBooted
10163 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010164 pw.println(" mGoingToSleep=" + mGoingToSleep);
10165 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -070010166 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010167 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010168
10169 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010170 }
10171
10172 /**
10173 * There are three ways to call this:
10174 * - no service specified: dump all the services
10175 * - a flattened component name that matched an existing service was specified as the
10176 * first arg: dump that one service
10177 * - the first arg isn't the flattened component name of an existing service:
10178 * dump all services whose component contains the first arg as a substring
10179 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010180 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
10181 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 String[] newArgs;
10183 String componentNameString;
10184 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -080010185 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010186 componentNameString = null;
10187 newArgs = EMPTY_STRING_ARRAY;
10188 r = null;
10189 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010190 componentNameString = args[opti];
10191 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010192 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
10193 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010194 newArgs = new String[args.length - opti];
10195 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010196 }
10197
10198 if (r != null) {
10199 dumpService(fd, pw, r, newArgs);
10200 } else {
10201 for (ServiceRecord r1 : mServices.values()) {
10202 if (componentNameString == null
10203 || r1.name.flattenToString().contains(componentNameString)) {
10204 dumpService(fd, pw, r1, newArgs);
10205 }
10206 }
10207 }
10208 }
10209
10210 /**
10211 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
10212 * there is a thread associated with the service.
10213 */
10214 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
10215 pw.println(" Service " + r.name.flattenToString());
10216 if (r.app != null && r.app.thread != null) {
10217 try {
10218 // flush anything that is already in the PrintWriter since the thread is going
10219 // to write to the file descriptor directly
10220 pw.flush();
10221 r.app.thread.dumpService(fd, r, args);
10222 pw.print("\n");
10223 } catch (RemoteException e) {
10224 pw.println("got a RemoteException while dumping the service");
10225 }
10226 }
10227 }
10228
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010229 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10230 int opti, boolean dumpAll) {
10231 boolean needSep = false;
10232
10233 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234 if (mRegisteredReceivers.size() > 0) {
10235 pw.println(" ");
10236 pw.println(" Registered Receivers:");
10237 Iterator it = mRegisteredReceivers.values().iterator();
10238 while (it.hasNext()) {
10239 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010240 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010241 r.dump(pw, " ");
10242 }
10243 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010245 pw.println(" ");
10246 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010247 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010248 needSep = true;
10249 }
10250
10251 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
10252 || mPendingBroadcast != null) {
10253 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010254 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010255 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010256 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010257 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10258 pw.println(" Broadcast #" + i + ":");
10259 mParallelBroadcasts.get(i).dump(pw, " ");
10260 }
10261 if (mOrderedBroadcasts.size() > 0) {
10262 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010263 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010264 }
10265 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10266 pw.println(" Serialized Broadcast #" + i + ":");
10267 mOrderedBroadcasts.get(i).dump(pw, " ");
10268 }
10269 pw.println(" ");
10270 pw.println(" Pending broadcast:");
10271 if (mPendingBroadcast != null) {
10272 mPendingBroadcast.dump(pw, " ");
10273 } else {
10274 pw.println(" (null)");
10275 }
10276 needSep = true;
10277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010278
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010279 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010280 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -080010281 pw.println(" Historical broadcasts:");
10282 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
10283 BroadcastRecord r = mBroadcastHistory[i];
10284 if (r == null) {
10285 break;
10286 }
10287 pw.println(" Historical Broadcast #" + i + ":");
10288 r.dump(pw, " ");
10289 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010290 needSep = true;
10291 }
10292
10293 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010294 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010295 pw.println(" Sticky broadcasts:");
10296 StringBuilder sb = new StringBuilder(128);
10297 for (Map.Entry<String, ArrayList<Intent>> ent
10298 : mStickyBroadcasts.entrySet()) {
10299 pw.print(" * Sticky action "); pw.print(ent.getKey());
10300 pw.println(":");
10301 ArrayList<Intent> intents = ent.getValue();
10302 final int N = intents.size();
10303 for (int i=0; i<N; i++) {
10304 sb.setLength(0);
10305 sb.append(" Intent: ");
10306 intents.get(i).toShortString(sb, true, false);
10307 pw.println(sb.toString());
10308 Bundle bundle = intents.get(i).getExtras();
10309 if (bundle != null) {
10310 pw.print(" ");
10311 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010312 }
10313 }
10314 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010315 needSep = true;
10316 }
10317
10318 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010319 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010320 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010321 pw.println(" mHandler:");
10322 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010323 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010324 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010325
10326 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327 }
10328
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010329 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10330 int opti, boolean dumpAll) {
10331 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010332
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010333 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010334 if (mServices.size() > 0) {
10335 pw.println(" Active services:");
10336 Iterator<ServiceRecord> it = mServices.values().iterator();
10337 while (it.hasNext()) {
10338 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010339 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010340 r.dump(pw, " ");
10341 }
10342 needSep = true;
10343 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010344 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010345
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010346 if (mPendingServices.size() > 0) {
10347 if (needSep) pw.println(" ");
10348 pw.println(" Pending services:");
10349 for (int i=0; i<mPendingServices.size(); i++) {
10350 ServiceRecord r = mPendingServices.get(i);
10351 pw.print(" * Pending "); pw.println(r);
10352 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010353 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010354 needSep = true;
10355 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010356
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010357 if (mRestartingServices.size() > 0) {
10358 if (needSep) pw.println(" ");
10359 pw.println(" Restarting services:");
10360 for (int i=0; i<mRestartingServices.size(); i++) {
10361 ServiceRecord r = mRestartingServices.get(i);
10362 pw.print(" * Restarting "); pw.println(r);
10363 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010364 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010365 needSep = true;
10366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010368 if (mStoppingServices.size() > 0) {
10369 if (needSep) pw.println(" ");
10370 pw.println(" Stopping services:");
10371 for (int i=0; i<mStoppingServices.size(); i++) {
10372 ServiceRecord r = mStoppingServices.get(i);
10373 pw.print(" * Stopping "); pw.println(r);
10374 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010375 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010376 needSep = true;
10377 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010379 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010380 if (mServiceConnections.size() > 0) {
10381 if (needSep) pw.println(" ");
10382 pw.println(" Connection bindings to services:");
10383 Iterator<ConnectionRecord> it
10384 = mServiceConnections.values().iterator();
10385 while (it.hasNext()) {
10386 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010387 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010388 r.dump(pw, " ");
10389 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010390 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010391 }
10392 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010393
10394 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010395 }
10396
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010397 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10398 int opti, boolean dumpAll) {
10399 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010400
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010401 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010402 if (mProvidersByClass.size() > 0) {
10403 if (needSep) pw.println(" ");
10404 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010405 Iterator<Map.Entry<String, ContentProviderRecord>> it
10406 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010407 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010408 Map.Entry<String, ContentProviderRecord> e = it.next();
10409 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010410 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010411 r.dump(pw, " ");
10412 }
10413 needSep = true;
10414 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010415
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010416 if (mProvidersByName.size() > 0) {
10417 pw.println(" ");
10418 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010419 Iterator<Map.Entry<String, ContentProviderRecord>> it
10420 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010421 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010422 Map.Entry<String, ContentProviderRecord> e = it.next();
10423 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010424 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10425 pw.println(r);
10426 }
10427 needSep = true;
10428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010429 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010430
10431 if (mLaunchingProviders.size() > 0) {
10432 if (needSep) pw.println(" ");
10433 pw.println(" Launching content providers:");
10434 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10435 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10436 pw.println(mLaunchingProviders.get(i));
10437 }
10438 needSep = true;
10439 }
10440
10441 if (mGrantedUriPermissions.size() > 0) {
10442 pw.println();
10443 pw.println("Granted Uri Permissions:");
10444 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10445 int uid = mGrantedUriPermissions.keyAt(i);
10446 HashMap<Uri, UriPermission> perms
10447 = mGrantedUriPermissions.valueAt(i);
10448 pw.print(" * UID "); pw.print(uid);
10449 pw.println(" holds:");
10450 for (UriPermission perm : perms.values()) {
10451 pw.print(" "); pw.println(perm);
10452 perm.dump(pw, " ");
10453 }
10454 }
10455 needSep = true;
10456 }
10457
10458 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010459 }
10460
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010461 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10462 int opti, boolean dumpAll) {
10463 boolean needSep = false;
10464
10465 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010466 if (this.mIntentSenderRecords.size() > 0) {
10467 Iterator<WeakReference<PendingIntentRecord>> it
10468 = mIntentSenderRecords.values().iterator();
10469 while (it.hasNext()) {
10470 WeakReference<PendingIntentRecord> ref = it.next();
10471 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010472 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010473 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010474 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010475 rec.dump(pw, " ");
10476 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010477 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010478 }
10479 }
10480 }
10481 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010482
10483 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010484 }
10485
10486 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010487 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010488 TaskRecord lastTask = null;
10489 for (int i=list.size()-1; i>=0; i--) {
10490 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010491 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010492 if (lastTask != r.task) {
10493 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010494 pw.print(prefix);
10495 pw.print(full ? "* " : " ");
10496 pw.println(lastTask);
10497 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010498 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010499 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010500 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010501 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10502 pw.print(" #"); pw.print(i); pw.print(": ");
10503 pw.println(r);
10504 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010505 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010507 }
10508 }
10509
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010510 private static String buildOomTag(String prefix, String space, int val, int base) {
10511 if (val == base) {
10512 if (space == null) return prefix;
10513 return prefix + " ";
10514 }
10515 return prefix + "+" + Integer.toString(val-base);
10516 }
10517
10518 private static final int dumpProcessList(PrintWriter pw,
10519 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010520 String prefix, String normalLabel, String persistentLabel,
10521 boolean inclOomAdj) {
10522 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010523 final int N = list.size()-1;
10524 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010525 ProcessRecord r = (ProcessRecord)list.get(i);
10526 if (false) {
10527 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10528 + " #" + i + ":");
10529 r.dump(pw, prefix + " ");
10530 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010531 String oomAdj;
10532 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010533 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010534 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010535 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10536 } else if (r.setAdj >= HOME_APP_ADJ) {
10537 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10538 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10539 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10540 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10541 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010542 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
10543 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
10544 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
10545 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010546 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10547 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10548 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10549 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010550 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010551 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010552 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010553 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010554 } else {
10555 oomAdj = Integer.toString(r.setAdj);
10556 }
10557 String schedGroup;
10558 switch (r.setSchedGroup) {
10559 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10560 schedGroup = "B";
10561 break;
10562 case Process.THREAD_GROUP_DEFAULT:
10563 schedGroup = "F";
10564 break;
10565 default:
10566 schedGroup = Integer.toString(r.setSchedGroup);
10567 break;
10568 }
10569 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010570 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010571 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010572 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010573 pw.print(prefix);
10574 pw.print(" ");
10575 if (r.adjTarget instanceof ComponentName) {
10576 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
10577 } else if (r.adjTarget != null) {
10578 pw.print(r.adjTarget.toString());
10579 } else {
10580 pw.print("{null}");
10581 }
10582 pw.print("<=");
10583 if (r.adjSource instanceof ProcessRecord) {
10584 pw.print("Proc{");
10585 pw.print(((ProcessRecord)r.adjSource).toShortString());
10586 pw.println("}");
10587 } else if (r.adjSource != null) {
10588 pw.println(r.adjSource.toString());
10589 } else {
10590 pw.println("{null}");
10591 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010593 } else {
10594 pw.println(String.format("%s%s #%2d: %s",
10595 prefix, (r.persistent ? persistentLabel : normalLabel),
10596 i, r.toString()));
10597 }
10598 if (r.persistent) {
10599 numPers++;
10600 }
10601 }
10602 return numPers;
10603 }
10604
Dianne Hackborn472ad872010-04-07 17:31:48 -070010605 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010606 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010607 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010608 long uptime = SystemClock.uptimeMillis();
10609 long realtime = SystemClock.elapsedRealtime();
10610
10611 if (isCheckinRequest) {
10612 // short checkin version
10613 pw.println(uptime + "," + realtime);
10614 pw.flush();
10615 } else {
10616 pw.println("Applications Memory Usage (kB):");
10617 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10618 }
10619 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10620 ProcessRecord r = (ProcessRecord)list.get(i);
10621 if (r.thread != null) {
10622 if (!isCheckinRequest) {
10623 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10624 pw.flush();
10625 }
10626 try {
10627 r.thread.asBinder().dump(fd, args);
10628 } catch (RemoteException e) {
10629 if (!isCheckinRequest) {
10630 pw.println("Got RemoteException!");
10631 pw.flush();
10632 }
10633 }
10634 }
10635 }
10636 }
10637
10638 /**
10639 * Searches array of arguments for the specified string
10640 * @param args array of argument strings
10641 * @param value value to search for
10642 * @return true if the value is contained in the array
10643 */
10644 private static boolean scanArgs(String[] args, String value) {
10645 if (args != null) {
10646 for (String arg : args) {
10647 if (value.equals(arg)) {
10648 return true;
10649 }
10650 }
10651 }
10652 return false;
10653 }
10654
Dianne Hackborn75b03852009-06-12 15:43:26 -070010655 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010656 int count = mHistory.size();
10657
10658 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010659 int index = -1;
10660 for (int i=count-1; i>=0; i--) {
10661 Object o = mHistory.get(i);
10662 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010663 index = i;
10664 break;
10665 }
10666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667
10668 return index;
10669 }
10670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010671 private final void killServicesLocked(ProcessRecord app,
10672 boolean allowRestart) {
10673 // Report disconnected services.
10674 if (false) {
10675 // XXX we are letting the client link to the service for
10676 // death notifications.
10677 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010678 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010679 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010680 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010681 if (r.connections.size() > 0) {
10682 Iterator<ConnectionRecord> jt
10683 = r.connections.values().iterator();
10684 while (jt.hasNext()) {
10685 ConnectionRecord c = jt.next();
10686 if (c.binding.client != app) {
10687 try {
10688 //c.conn.connected(r.className, null);
10689 } catch (Exception e) {
10690 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010691 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010692 + r.shortName
10693 + " from app " + app.processName, e);
10694 }
10695 }
10696 }
10697 }
10698 }
10699 }
10700 }
10701
10702 // Clean up any connections this application has to other services.
10703 if (app.connections.size() > 0) {
10704 Iterator<ConnectionRecord> it = app.connections.iterator();
10705 while (it.hasNext()) {
10706 ConnectionRecord r = it.next();
10707 removeConnectionLocked(r, app, null);
10708 }
10709 }
10710 app.connections.clear();
10711
10712 if (app.services.size() != 0) {
10713 // Any services running in the application need to be placed
10714 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010715 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010716 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010717 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010718 synchronized (sr.stats.getBatteryStats()) {
10719 sr.stats.stopLaunchedLocked();
10720 }
10721 sr.app = null;
10722 sr.executeNesting = 0;
10723 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010724
10725 boolean hasClients = sr.bindings.size() > 0;
10726 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010727 Iterator<IntentBindRecord> bindings
10728 = sr.bindings.values().iterator();
10729 while (bindings.hasNext()) {
10730 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010731 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010732 + ": shouldUnbind=" + b.hasBound);
10733 b.binder = null;
10734 b.requested = b.received = b.hasBound = false;
10735 }
10736 }
10737
10738 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010739 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010740 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010741 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010742 sr.crashCount, sr.shortName, app.pid);
10743 bringDownServiceLocked(sr, true);
10744 } else if (!allowRestart) {
10745 bringDownServiceLocked(sr, true);
10746 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010747 boolean canceled = scheduleServiceRestartLocked(sr, true);
10748
10749 // Should the service remain running? Note that in the
10750 // extreme case of so many attempts to deliver a command
10751 // that it failed, that we also will stop it here.
10752 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10753 if (sr.pendingStarts.size() == 0) {
10754 sr.startRequested = false;
10755 if (!hasClients) {
10756 // Whoops, no reason to restart!
10757 bringDownServiceLocked(sr, true);
10758 }
10759 }
10760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010761 }
10762 }
10763
10764 if (!allowRestart) {
10765 app.services.clear();
10766 }
10767 }
10768
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010769 // Make sure we have no more records on the stopping list.
10770 int i = mStoppingServices.size();
10771 while (i > 0) {
10772 i--;
10773 ServiceRecord sr = mStoppingServices.get(i);
10774 if (sr.app == app) {
10775 mStoppingServices.remove(i);
10776 }
10777 }
10778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010779 app.executingServices.clear();
10780 }
10781
10782 private final void removeDyingProviderLocked(ProcessRecord proc,
10783 ContentProviderRecord cpr) {
10784 synchronized (cpr) {
10785 cpr.launchingApp = null;
10786 cpr.notifyAll();
10787 }
10788
10789 mProvidersByClass.remove(cpr.info.name);
10790 String names[] = cpr.info.authority.split(";");
10791 for (int j = 0; j < names.length; j++) {
10792 mProvidersByName.remove(names[j]);
10793 }
10794
10795 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10796 while (cit.hasNext()) {
10797 ProcessRecord capp = cit.next();
10798 if (!capp.persistent && capp.thread != null
10799 && capp.pid != 0
10800 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010801 Slog.i(TAG, "Kill " + capp.processName
10802 + " (pid " + capp.pid + "): provider " + cpr.info.name
10803 + " in dying process " + proc.processName);
10804 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10805 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010806 Process.killProcess(capp.pid);
10807 }
10808 }
10809
10810 mLaunchingProviders.remove(cpr);
10811 }
10812
10813 /**
10814 * Main code for cleaning up a process when it has gone away. This is
10815 * called both as a result of the process dying, or directly when stopping
10816 * a process when running in single process mode.
10817 */
10818 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10819 boolean restarting, int index) {
10820 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010821 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010822 }
10823
Dianne Hackborn36124872009-10-08 16:22:03 -070010824 mProcessesToGc.remove(app);
10825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010826 // Dismiss any open dialogs.
10827 if (app.crashDialog != null) {
10828 app.crashDialog.dismiss();
10829 app.crashDialog = null;
10830 }
10831 if (app.anrDialog != null) {
10832 app.anrDialog.dismiss();
10833 app.anrDialog = null;
10834 }
10835 if (app.waitDialog != null) {
10836 app.waitDialog.dismiss();
10837 app.waitDialog = null;
10838 }
10839
10840 app.crashing = false;
10841 app.notResponding = false;
10842
10843 app.resetPackageList();
10844 app.thread = null;
10845 app.forcingToForeground = null;
10846 app.foregroundServices = false;
10847
10848 killServicesLocked(app, true);
10849
10850 boolean restart = false;
10851
10852 int NL = mLaunchingProviders.size();
10853
10854 // Remove published content providers.
10855 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010856 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010857 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010858 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 cpr.provider = null;
10860 cpr.app = null;
10861
10862 // See if someone is waiting for this provider... in which
10863 // case we don't remove it, but just let it restart.
10864 int i = 0;
10865 if (!app.bad) {
10866 for (; i<NL; i++) {
10867 if (mLaunchingProviders.get(i) == cpr) {
10868 restart = true;
10869 break;
10870 }
10871 }
10872 } else {
10873 i = NL;
10874 }
10875
10876 if (i >= NL) {
10877 removeDyingProviderLocked(app, cpr);
10878 NL = mLaunchingProviders.size();
10879 }
10880 }
10881 app.pubProviders.clear();
10882 }
10883
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010884 // Take care of any launching providers waiting for this process.
10885 if (checkAppInLaunchingProvidersLocked(app, false)) {
10886 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010887 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010889 // Unregister from connected content providers.
10890 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010891 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010892 while (it.hasNext()) {
10893 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10894 cpr.clients.remove(app);
10895 }
10896 app.conProviders.clear();
10897 }
10898
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010899 // At this point there may be remaining entries in mLaunchingProviders
10900 // where we were the only one waiting, so they are no longer of use.
10901 // Look for these and clean up if found.
10902 // XXX Commented out for now. Trying to figure out a way to reproduce
10903 // the actual situation to identify what is actually going on.
10904 if (false) {
10905 for (int i=0; i<NL; i++) {
10906 ContentProviderRecord cpr = (ContentProviderRecord)
10907 mLaunchingProviders.get(i);
10908 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10909 synchronized (cpr) {
10910 cpr.launchingApp = null;
10911 cpr.notifyAll();
10912 }
10913 }
10914 }
10915 }
10916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 skipCurrentReceiverLocked(app);
10918
10919 // Unregister any receivers.
10920 if (app.receivers.size() > 0) {
10921 Iterator<ReceiverList> it = app.receivers.iterator();
10922 while (it.hasNext()) {
10923 removeReceiverLocked(it.next());
10924 }
10925 app.receivers.clear();
10926 }
10927
Christopher Tate181fafa2009-05-14 11:12:14 -070010928 // If the app is undergoing backup, tell the backup manager about it
10929 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010930 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010931 try {
10932 IBackupManager bm = IBackupManager.Stub.asInterface(
10933 ServiceManager.getService(Context.BACKUP_SERVICE));
10934 bm.agentDisconnected(app.info.packageName);
10935 } catch (RemoteException e) {
10936 // can't happen; backup manager is local
10937 }
10938 }
10939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010940 // If the caller is restarting this app, then leave it in its
10941 // current lists and let the caller take care of it.
10942 if (restarting) {
10943 return;
10944 }
10945
10946 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010947 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 "Removing non-persistent process during cleanup: " + app);
10949 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010950 if (mHeavyWeightProcess == app) {
10951 mHeavyWeightProcess = null;
10952 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
10953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 } else if (!app.removed) {
10955 // This app is persistent, so we need to keep its record around.
10956 // If it is not already on the pending app list, add it there
10957 // and start a new process for it.
10958 app.thread = null;
10959 app.forcingToForeground = null;
10960 app.foregroundServices = false;
10961 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10962 mPersistentStartingProcesses.add(app);
10963 restart = true;
10964 }
10965 }
10966 mProcessesOnHold.remove(app);
10967
The Android Open Source Project4df24232009-03-05 14:34:35 -080010968 if (app == mHomeProcess) {
10969 mHomeProcess = null;
10970 }
10971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010972 if (restart) {
10973 // We have components that still need to be running in the
10974 // process, so re-launch it.
10975 mProcessNames.put(app.processName, app.info.uid, app);
10976 startProcessLocked(app, "restart", app.processName);
10977 } else if (app.pid > 0 && app.pid != MY_PID) {
10978 // Goodbye!
10979 synchronized (mPidsSelfLocked) {
10980 mPidsSelfLocked.remove(app.pid);
10981 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10982 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010983 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010984 }
10985 }
10986
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010987 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10988 // Look through the content providers we are waiting to have launched,
10989 // and if any run in this process then either schedule a restart of
10990 // the process or kill the client waiting for it if this process has
10991 // gone bad.
10992 int NL = mLaunchingProviders.size();
10993 boolean restart = false;
10994 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010995 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010996 if (cpr.launchingApp == app) {
10997 if (!alwaysBad && !app.bad) {
10998 restart = true;
10999 } else {
11000 removeDyingProviderLocked(app, cpr);
11001 NL = mLaunchingProviders.size();
11002 }
11003 }
11004 }
11005 return restart;
11006 }
11007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 // =========================================================
11009 // SERVICES
11010 // =========================================================
11011
11012 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
11013 ActivityManager.RunningServiceInfo info =
11014 new ActivityManager.RunningServiceInfo();
11015 info.service = r.name;
11016 if (r.app != null) {
11017 info.pid = r.app.pid;
11018 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011019 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011020 info.process = r.processName;
11021 info.foreground = r.isForeground;
11022 info.activeSince = r.createTime;
11023 info.started = r.startRequested;
11024 info.clientCount = r.connections.size();
11025 info.crashCount = r.crashCount;
11026 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011027 if (r.isForeground) {
11028 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
11029 }
11030 if (r.startRequested) {
11031 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
11032 }
Dan Egnor42471dd2010-01-07 17:25:22 -080011033 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011034 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
11035 }
11036 if (r.app != null && r.app.persistent) {
11037 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
11038 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011039 for (ConnectionRecord conn : r.connections.values()) {
11040 if (conn.clientLabel != 0) {
11041 info.clientPackage = conn.binding.client.info.packageName;
11042 info.clientLabel = conn.clientLabel;
11043 break;
11044 }
11045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011046 return info;
11047 }
11048
11049 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
11050 int flags) {
11051 synchronized (this) {
11052 ArrayList<ActivityManager.RunningServiceInfo> res
11053 = new ArrayList<ActivityManager.RunningServiceInfo>();
11054
11055 if (mServices.size() > 0) {
11056 Iterator<ServiceRecord> it = mServices.values().iterator();
11057 while (it.hasNext() && res.size() < maxNum) {
11058 res.add(makeRunningServiceInfoLocked(it.next()));
11059 }
11060 }
11061
11062 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
11063 ServiceRecord r = mRestartingServices.get(i);
11064 ActivityManager.RunningServiceInfo info =
11065 makeRunningServiceInfoLocked(r);
11066 info.restarting = r.nextRestartTime;
11067 res.add(info);
11068 }
11069
11070 return res;
11071 }
11072 }
11073
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011074 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
11075 synchronized (this) {
11076 ServiceRecord r = mServices.get(name);
11077 if (r != null) {
11078 for (ConnectionRecord conn : r.connections.values()) {
11079 if (conn.clientIntent != null) {
11080 return conn.clientIntent;
11081 }
11082 }
11083 }
11084 }
11085 return null;
11086 }
11087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011088 private final ServiceRecord findServiceLocked(ComponentName name,
11089 IBinder token) {
11090 ServiceRecord r = mServices.get(name);
11091 return r == token ? r : null;
11092 }
11093
11094 private final class ServiceLookupResult {
11095 final ServiceRecord record;
11096 final String permission;
11097
11098 ServiceLookupResult(ServiceRecord _record, String _permission) {
11099 record = _record;
11100 permission = _permission;
11101 }
11102 };
11103
11104 private ServiceLookupResult findServiceLocked(Intent service,
11105 String resolvedType) {
11106 ServiceRecord r = null;
11107 if (service.getComponent() != null) {
11108 r = mServices.get(service.getComponent());
11109 }
11110 if (r == null) {
11111 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11112 r = mServicesByIntent.get(filter);
11113 }
11114
11115 if (r == null) {
11116 try {
11117 ResolveInfo rInfo =
11118 ActivityThread.getPackageManager().resolveService(
11119 service, resolvedType, 0);
11120 ServiceInfo sInfo =
11121 rInfo != null ? rInfo.serviceInfo : null;
11122 if (sInfo == null) {
11123 return null;
11124 }
11125
11126 ComponentName name = new ComponentName(
11127 sInfo.applicationInfo.packageName, sInfo.name);
11128 r = mServices.get(name);
11129 } catch (RemoteException ex) {
11130 // pm is in same process, this will never happen.
11131 }
11132 }
11133 if (r != null) {
11134 int callingPid = Binder.getCallingPid();
11135 int callingUid = Binder.getCallingUid();
11136 if (checkComponentPermission(r.permission,
11137 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11138 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011139 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011140 + " from pid=" + callingPid
11141 + ", uid=" + callingUid
11142 + " requires " + r.permission);
11143 return new ServiceLookupResult(null, r.permission);
11144 }
11145 return new ServiceLookupResult(r, null);
11146 }
11147 return null;
11148 }
11149
11150 private class ServiceRestarter implements Runnable {
11151 private ServiceRecord mService;
11152
11153 void setService(ServiceRecord service) {
11154 mService = service;
11155 }
11156
11157 public void run() {
11158 synchronized(ActivityManagerService.this) {
11159 performServiceRestartLocked(mService);
11160 }
11161 }
11162 }
11163
11164 private ServiceLookupResult retrieveServiceLocked(Intent service,
11165 String resolvedType, int callingPid, int callingUid) {
11166 ServiceRecord r = null;
11167 if (service.getComponent() != null) {
11168 r = mServices.get(service.getComponent());
11169 }
11170 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11171 r = mServicesByIntent.get(filter);
11172 if (r == null) {
11173 try {
11174 ResolveInfo rInfo =
11175 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011176 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011177 ServiceInfo sInfo =
11178 rInfo != null ? rInfo.serviceInfo : null;
11179 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011180 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011181 ": not found");
11182 return null;
11183 }
11184
11185 ComponentName name = new ComponentName(
11186 sInfo.applicationInfo.packageName, sInfo.name);
11187 r = mServices.get(name);
11188 if (r == null) {
11189 filter = new Intent.FilterComparison(service.cloneFilter());
11190 ServiceRestarter res = new ServiceRestarter();
11191 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11192 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11193 synchronized (stats) {
11194 ss = stats.getServiceStatsLocked(
11195 sInfo.applicationInfo.uid, sInfo.packageName,
11196 sInfo.name);
11197 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080011198 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199 res.setService(r);
11200 mServices.put(name, r);
11201 mServicesByIntent.put(filter, r);
11202
11203 // Make sure this component isn't in the pending list.
11204 int N = mPendingServices.size();
11205 for (int i=0; i<N; i++) {
11206 ServiceRecord pr = mPendingServices.get(i);
11207 if (pr.name.equals(name)) {
11208 mPendingServices.remove(i);
11209 i--;
11210 N--;
11211 }
11212 }
11213 }
11214 } catch (RemoteException ex) {
11215 // pm is in same process, this will never happen.
11216 }
11217 }
11218 if (r != null) {
11219 if (checkComponentPermission(r.permission,
11220 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11221 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011222 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011223 + " from pid=" + Binder.getCallingPid()
11224 + ", uid=" + Binder.getCallingUid()
11225 + " requires " + r.permission);
11226 return new ServiceLookupResult(null, r.permission);
11227 }
11228 return new ServiceLookupResult(r, null);
11229 }
11230 return null;
11231 }
11232
11233 private final void bumpServiceExecutingLocked(ServiceRecord r) {
11234 long now = SystemClock.uptimeMillis();
11235 if (r.executeNesting == 0 && r.app != null) {
11236 if (r.app.executingServices.size() == 0) {
11237 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11238 msg.obj = r.app;
11239 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
11240 }
11241 r.app.executingServices.add(r);
11242 }
11243 r.executeNesting++;
11244 r.executingStart = now;
11245 }
11246
11247 private final void sendServiceArgsLocked(ServiceRecord r,
11248 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011249 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011250 if (N == 0) {
11251 return;
11252 }
11253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011254 int i = 0;
11255 while (i < N) {
11256 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011257 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011258 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011259 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070011260 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011261 // If somehow we got a dummy start at the front, then
11262 // just drop it here.
11263 i++;
11264 continue;
11265 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 bumpServiceExecutingLocked(r);
11267 if (!oomAdjusted) {
11268 oomAdjusted = true;
11269 updateOomAdjLocked(r.app);
11270 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011271 int flags = 0;
11272 if (si.deliveryCount > 0) {
11273 flags |= Service.START_FLAG_RETRY;
11274 }
11275 if (si.doneExecutingCount > 0) {
11276 flags |= Service.START_FLAG_REDELIVERY;
11277 }
11278 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
11279 si.deliveredTime = SystemClock.uptimeMillis();
11280 r.deliveredStarts.add(si);
11281 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011283 } catch (RemoteException e) {
11284 // Remote process gone... we'll let the normal cleanup take
11285 // care of this.
11286 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011287 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011288 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011289 break;
11290 }
11291 }
11292 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011293 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011294 } else {
11295 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011296 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011297 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011298 }
11299 }
11300 }
11301
11302 private final boolean requestServiceBindingLocked(ServiceRecord r,
11303 IntentBindRecord i, boolean rebind) {
11304 if (r.app == null || r.app.thread == null) {
11305 // If service is not currently running, can't yet bind.
11306 return false;
11307 }
11308 if ((!i.requested || rebind) && i.apps.size() > 0) {
11309 try {
11310 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011311 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 + ": shouldUnbind=" + i.hasBound);
11313 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11314 if (!rebind) {
11315 i.requested = true;
11316 }
11317 i.hasBound = true;
11318 i.doRebind = false;
11319 } catch (RemoteException e) {
11320 return false;
11321 }
11322 }
11323 return true;
11324 }
11325
11326 private final void requestServiceBindingsLocked(ServiceRecord r) {
11327 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11328 while (bindings.hasNext()) {
11329 IntentBindRecord i = bindings.next();
11330 if (!requestServiceBindingLocked(r, i, false)) {
11331 break;
11332 }
11333 }
11334 }
11335
11336 private final void realStartServiceLocked(ServiceRecord r,
11337 ProcessRecord app) throws RemoteException {
11338 if (app.thread == null) {
11339 throw new RemoteException();
11340 }
11341
11342 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011343 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011344
11345 app.services.add(r);
11346 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011347 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011348
11349 boolean created = false;
11350 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011351 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011352 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011353 mStringBuilder.setLength(0);
11354 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011355 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011356 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011357 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011358 synchronized (r.stats.getBatteryStats()) {
11359 r.stats.startLaunchedLocked();
11360 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011361 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011363 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011364 created = true;
11365 } finally {
11366 if (!created) {
11367 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011368 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011369 }
11370 }
11371
11372 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011373
11374 // If the service is in the started state, and there are no
11375 // pending arguments, then fake up one so its onStartCommand() will
11376 // be called.
11377 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11378 r.lastStartId++;
11379 if (r.lastStartId < 1) {
11380 r.lastStartId = 1;
11381 }
11382 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11383 }
11384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011385 sendServiceArgsLocked(r, true);
11386 }
11387
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011388 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11389 boolean allowCancel) {
11390 boolean canceled = false;
11391
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011392 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011393 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011394 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011395
11396 // Any delivered but not yet finished starts should be put back
11397 // on the pending list.
11398 final int N = r.deliveredStarts.size();
11399 if (N > 0) {
11400 for (int i=N-1; i>=0; i--) {
11401 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11402 if (si.intent == null) {
11403 // We'll generate this again if needed.
11404 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11405 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11406 r.pendingStarts.add(0, si);
11407 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11408 dur *= 2;
11409 if (minDuration < dur) minDuration = dur;
11410 if (resetTime < dur) resetTime = dur;
11411 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011412 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011413 + r.name);
11414 canceled = true;
11415 }
11416 }
11417 r.deliveredStarts.clear();
11418 }
11419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011420 r.totalRestartCount++;
11421 if (r.restartDelay == 0) {
11422 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011423 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011424 } else {
11425 // If it has been a "reasonably long time" since the service
11426 // was started, then reset our restart duration back to
11427 // the beginning, so we don't infinitely increase the duration
11428 // on a service that just occasionally gets killed (which is
11429 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011430 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011431 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011432 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011433 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011434 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011435 if (r.restartDelay < minDuration) {
11436 r.restartDelay = minDuration;
11437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011438 }
11439 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011440
11441 r.nextRestartTime = now + r.restartDelay;
11442
11443 // Make sure that we don't end up restarting a bunch of services
11444 // all at the same time.
11445 boolean repeat;
11446 do {
11447 repeat = false;
11448 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11449 ServiceRecord r2 = mRestartingServices.get(i);
11450 if (r2 != r && r.nextRestartTime
11451 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11452 && r.nextRestartTime
11453 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11454 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11455 r.restartDelay = r.nextRestartTime - now;
11456 repeat = true;
11457 break;
11458 }
11459 }
11460 } while (repeat);
11461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011462 if (!mRestartingServices.contains(r)) {
11463 mRestartingServices.add(r);
11464 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011465
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011466 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011468 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011469 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011471 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011472 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011473 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474 r.shortName, r.restartDelay);
11475
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011476 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011477 }
11478
11479 final void performServiceRestartLocked(ServiceRecord r) {
11480 if (!mRestartingServices.contains(r)) {
11481 return;
11482 }
11483 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11484 }
11485
11486 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11487 if (r.restartDelay == 0) {
11488 return false;
11489 }
11490 r.resetRestartCounter();
11491 mRestartingServices.remove(r);
11492 mHandler.removeCallbacks(r.restarter);
11493 return true;
11494 }
11495
11496 private final boolean bringUpServiceLocked(ServiceRecord r,
11497 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011498 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011499 //r.dump(" ");
11500
Dianne Hackborn36124872009-10-08 16:22:03 -070011501 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011502 sendServiceArgsLocked(r, false);
11503 return true;
11504 }
11505
11506 if (!whileRestarting && r.restartDelay > 0) {
11507 // If waiting for a restart, then do nothing.
11508 return true;
11509 }
11510
Joe Onorato8a9b2202010-02-26 18:56:32 -080011511 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011512 + " " + r.intent);
11513
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011514 // We are now bringing the service up, so no longer in the
11515 // restarting state.
11516 mRestartingServices.remove(r);
11517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518 final String appName = r.processName;
11519 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11520 if (app != null && app.thread != null) {
11521 try {
11522 realStartServiceLocked(r, app);
11523 return true;
11524 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011525 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011526 }
11527
11528 // If a dead object exception was thrown -- fall through to
11529 // restart the application.
11530 }
11531
Dianne Hackborn36124872009-10-08 16:22:03 -070011532 // Not running -- get it started, and enqueue this service record
11533 // to be executed when the app comes up.
11534 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11535 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011536 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011537 + r.appInfo.packageName + "/"
11538 + r.appInfo.uid + " for service "
11539 + r.intent.getIntent() + ": process is bad");
11540 bringDownServiceLocked(r, true);
11541 return false;
11542 }
11543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011544 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011545 mPendingServices.add(r);
11546 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011548 return true;
11549 }
11550
11551 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011552 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011553 //r.dump(" ");
11554
11555 // Does it still need to run?
11556 if (!force && r.startRequested) {
11557 return;
11558 }
11559 if (r.connections.size() > 0) {
11560 if (!force) {
11561 // XXX should probably keep a count of the number of auto-create
11562 // connections directly in the service.
11563 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11564 while (it.hasNext()) {
11565 ConnectionRecord cr = it.next();
11566 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11567 return;
11568 }
11569 }
11570 }
11571
11572 // Report to all of the connections that the service is no longer
11573 // available.
11574 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11575 while (it.hasNext()) {
11576 ConnectionRecord c = it.next();
11577 try {
11578 // todo: shouldn't be a synchronous call!
11579 c.conn.connected(r.name, null);
11580 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011581 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011582 " to connection " + c.conn.asBinder() +
11583 " (in " + c.binding.client.processName + ")", e);
11584 }
11585 }
11586 }
11587
11588 // Tell the service that it has been unbound.
11589 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11590 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11591 while (it.hasNext()) {
11592 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011593 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 + ": hasBound=" + ibr.hasBound);
11595 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11596 try {
11597 bumpServiceExecutingLocked(r);
11598 updateOomAdjLocked(r.app);
11599 ibr.hasBound = false;
11600 r.app.thread.scheduleUnbindService(r,
11601 ibr.intent.getIntent());
11602 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011603 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604 + r.shortName, e);
11605 serviceDoneExecutingLocked(r, true);
11606 }
11607 }
11608 }
11609 }
11610
Joe Onorato8a9b2202010-02-26 18:56:32 -080011611 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011612 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011613 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 System.identityHashCode(r), r.shortName,
11615 (r.app != null) ? r.app.pid : -1);
11616
11617 mServices.remove(r.name);
11618 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011619 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620 r.totalRestartCount = 0;
11621 unscheduleServiceRestartLocked(r);
11622
11623 // Also make sure it is not on the pending list.
11624 int N = mPendingServices.size();
11625 for (int i=0; i<N; i++) {
11626 if (mPendingServices.get(i) == r) {
11627 mPendingServices.remove(i);
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 pending service: " + r.shortName);
11630 i--;
11631 N--;
11632 }
11633 }
11634
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011635 r.cancelNotification();
11636 r.isForeground = false;
11637 r.foregroundId = 0;
11638 r.foregroundNoti = null;
11639
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011640 // Clear start entries.
11641 r.deliveredStarts.clear();
11642 r.pendingStarts.clear();
11643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011644 if (r.app != null) {
11645 synchronized (r.stats.getBatteryStats()) {
11646 r.stats.stopLaunchedLocked();
11647 }
11648 r.app.services.remove(r);
11649 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011650 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011651 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011652 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011653 bumpServiceExecutingLocked(r);
11654 mStoppingServices.add(r);
11655 updateOomAdjLocked(r.app);
11656 r.app.thread.scheduleStopService(r);
11657 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011658 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011659 + r.shortName, e);
11660 serviceDoneExecutingLocked(r, true);
11661 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011662 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011663 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011664 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011665 TAG, "Removed service that has no process: " + r.shortName);
11666 }
11667 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011668 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011669 TAG, "Removed service that is not running: " + r.shortName);
11670 }
11671 }
11672
11673 ComponentName startServiceLocked(IApplicationThread caller,
11674 Intent service, String resolvedType,
11675 int callingPid, int callingUid) {
11676 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011677 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011678 + " type=" + resolvedType + " args=" + service.getExtras());
11679
11680 if (caller != null) {
11681 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11682 if (callerApp == null) {
11683 throw new SecurityException(
11684 "Unable to find app for caller " + caller
11685 + " (pid=" + Binder.getCallingPid()
11686 + ") when starting service " + service);
11687 }
11688 }
11689
11690 ServiceLookupResult res =
11691 retrieveServiceLocked(service, resolvedType,
11692 callingPid, callingUid);
11693 if (res == null) {
11694 return null;
11695 }
11696 if (res.record == null) {
11697 return new ComponentName("!", res.permission != null
11698 ? res.permission : "private to package");
11699 }
11700 ServiceRecord r = res.record;
11701 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011702 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011703 + r.shortName);
11704 }
11705 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011706 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011707 r.lastStartId++;
11708 if (r.lastStartId < 1) {
11709 r.lastStartId = 1;
11710 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011711 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011712 r.lastActivity = SystemClock.uptimeMillis();
11713 synchronized (r.stats.getBatteryStats()) {
11714 r.stats.startRunningLocked();
11715 }
11716 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11717 return new ComponentName("!", "Service process is bad");
11718 }
11719 return r.name;
11720 }
11721 }
11722
11723 public ComponentName startService(IApplicationThread caller, Intent service,
11724 String resolvedType) {
11725 // Refuse possible leaked file descriptors
11726 if (service != null && service.hasFileDescriptors() == true) {
11727 throw new IllegalArgumentException("File descriptors passed in Intent");
11728 }
11729
11730 synchronized(this) {
11731 final int callingPid = Binder.getCallingPid();
11732 final int callingUid = Binder.getCallingUid();
11733 final long origId = Binder.clearCallingIdentity();
11734 ComponentName res = startServiceLocked(caller, service,
11735 resolvedType, callingPid, callingUid);
11736 Binder.restoreCallingIdentity(origId);
11737 return res;
11738 }
11739 }
11740
11741 ComponentName startServiceInPackage(int uid,
11742 Intent service, String resolvedType) {
11743 synchronized(this) {
11744 final long origId = Binder.clearCallingIdentity();
11745 ComponentName res = startServiceLocked(null, service,
11746 resolvedType, -1, uid);
11747 Binder.restoreCallingIdentity(origId);
11748 return res;
11749 }
11750 }
11751
11752 public int stopService(IApplicationThread caller, Intent service,
11753 String resolvedType) {
11754 // Refuse possible leaked file descriptors
11755 if (service != null && service.hasFileDescriptors() == true) {
11756 throw new IllegalArgumentException("File descriptors passed in Intent");
11757 }
11758
11759 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011760 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011761 + " type=" + resolvedType);
11762
11763 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11764 if (caller != null && callerApp == null) {
11765 throw new SecurityException(
11766 "Unable to find app for caller " + caller
11767 + " (pid=" + Binder.getCallingPid()
11768 + ") when stopping service " + service);
11769 }
11770
11771 // If this service is active, make sure it is stopped.
11772 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11773 if (r != null) {
11774 if (r.record != null) {
11775 synchronized (r.record.stats.getBatteryStats()) {
11776 r.record.stats.stopRunningLocked();
11777 }
11778 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011779 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011780 final long origId = Binder.clearCallingIdentity();
11781 bringDownServiceLocked(r.record, false);
11782 Binder.restoreCallingIdentity(origId);
11783 return 1;
11784 }
11785 return -1;
11786 }
11787 }
11788
11789 return 0;
11790 }
11791
11792 public IBinder peekService(Intent service, String resolvedType) {
11793 // Refuse possible leaked file descriptors
11794 if (service != null && service.hasFileDescriptors() == true) {
11795 throw new IllegalArgumentException("File descriptors passed in Intent");
11796 }
11797
11798 IBinder ret = null;
11799
11800 synchronized(this) {
11801 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11802
11803 if (r != null) {
11804 // r.record is null if findServiceLocked() failed the caller permission check
11805 if (r.record == null) {
11806 throw new SecurityException(
11807 "Permission Denial: Accessing service " + r.record.name
11808 + " from pid=" + Binder.getCallingPid()
11809 + ", uid=" + Binder.getCallingUid()
11810 + " requires " + r.permission);
11811 }
11812 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11813 if (ib != null) {
11814 ret = ib.binder;
11815 }
11816 }
11817 }
11818
11819 return ret;
11820 }
11821
11822 public boolean stopServiceToken(ComponentName className, IBinder token,
11823 int startId) {
11824 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011825 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011826 + " " + token + " startId=" + startId);
11827 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011828 if (r != null) {
11829 if (startId >= 0) {
11830 // Asked to only stop if done with all work. Note that
11831 // to avoid leaks, we will take this as dropping all
11832 // start items up to and including this one.
11833 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11834 if (si != null) {
11835 while (r.deliveredStarts.size() > 0) {
11836 if (r.deliveredStarts.remove(0) == si) {
11837 break;
11838 }
11839 }
11840 }
11841
11842 if (r.lastStartId != startId) {
11843 return false;
11844 }
11845
11846 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011847 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011848 + " is last, but have " + r.deliveredStarts.size()
11849 + " remaining args");
11850 }
11851 }
11852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011853 synchronized (r.stats.getBatteryStats()) {
11854 r.stats.stopRunningLocked();
11855 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011856 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011857 }
11858 final long origId = Binder.clearCallingIdentity();
11859 bringDownServiceLocked(r, false);
11860 Binder.restoreCallingIdentity(origId);
11861 return true;
11862 }
11863 }
11864 return false;
11865 }
11866
11867 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011868 int id, Notification notification, boolean removeNotification) {
11869 final long origId = Binder.clearCallingIdentity();
11870 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011871 synchronized(this) {
11872 ServiceRecord r = findServiceLocked(className, token);
11873 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011874 if (id != 0) {
11875 if (notification == null) {
11876 throw new IllegalArgumentException("null notification");
11877 }
11878 if (r.foregroundId != id) {
11879 r.cancelNotification();
11880 r.foregroundId = id;
11881 }
11882 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11883 r.foregroundNoti = notification;
11884 r.isForeground = true;
11885 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011886 if (r.app != null) {
11887 updateServiceForegroundLocked(r.app, true);
11888 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011889 } else {
11890 if (r.isForeground) {
11891 r.isForeground = false;
11892 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011893 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011894 updateServiceForegroundLocked(r.app, true);
11895 }
11896 }
11897 if (removeNotification) {
11898 r.cancelNotification();
11899 r.foregroundId = 0;
11900 r.foregroundNoti = null;
11901 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011902 }
11903 }
11904 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011905 } finally {
11906 Binder.restoreCallingIdentity(origId);
11907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011908 }
11909
11910 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11911 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070011912 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011913 if (sr.isForeground) {
11914 anyForeground = true;
11915 break;
11916 }
11917 }
11918 if (anyForeground != proc.foregroundServices) {
11919 proc.foregroundServices = anyForeground;
11920 if (oomAdj) {
11921 updateOomAdjLocked();
11922 }
11923 }
11924 }
11925
11926 public int bindService(IApplicationThread caller, IBinder token,
11927 Intent service, String resolvedType,
11928 IServiceConnection connection, int flags) {
11929 // Refuse possible leaked file descriptors
11930 if (service != null && service.hasFileDescriptors() == true) {
11931 throw new IllegalArgumentException("File descriptors passed in Intent");
11932 }
11933
11934 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011935 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011936 + " type=" + resolvedType + " conn=" + connection.asBinder()
11937 + " flags=0x" + Integer.toHexString(flags));
11938 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11939 if (callerApp == null) {
11940 throw new SecurityException(
11941 "Unable to find app for caller " + caller
11942 + " (pid=" + Binder.getCallingPid()
11943 + ") when binding service " + service);
11944 }
11945
11946 HistoryRecord activity = null;
11947 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011948 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011949 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011950 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011951 return 0;
11952 }
11953 activity = (HistoryRecord)mHistory.get(aindex);
11954 }
11955
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011956 int clientLabel = 0;
11957 PendingIntent clientIntent = null;
11958
11959 if (callerApp.info.uid == Process.SYSTEM_UID) {
11960 // Hacky kind of thing -- allow system stuff to tell us
11961 // what they are, so we can report this elsewhere for
11962 // others to know why certain services are running.
11963 try {
11964 clientIntent = (PendingIntent)service.getParcelableExtra(
11965 Intent.EXTRA_CLIENT_INTENT);
11966 } catch (RuntimeException e) {
11967 }
11968 if (clientIntent != null) {
11969 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11970 if (clientLabel != 0) {
11971 // There are no useful extras in the intent, trash them.
11972 // System code calling with this stuff just needs to know
11973 // this will happen.
11974 service = service.cloneFilter();
11975 }
11976 }
11977 }
11978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011979 ServiceLookupResult res =
11980 retrieveServiceLocked(service, resolvedType,
11981 Binder.getCallingPid(), Binder.getCallingUid());
11982 if (res == null) {
11983 return 0;
11984 }
11985 if (res.record == null) {
11986 return -1;
11987 }
11988 ServiceRecord s = res.record;
11989
11990 final long origId = Binder.clearCallingIdentity();
11991
11992 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011993 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011994 + s.shortName);
11995 }
11996
11997 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11998 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011999 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012000
12001 IBinder binder = connection.asBinder();
12002 s.connections.put(binder, c);
12003 b.connections.add(c);
12004 if (activity != null) {
12005 if (activity.connections == null) {
12006 activity.connections = new HashSet<ConnectionRecord>();
12007 }
12008 activity.connections.add(c);
12009 }
12010 b.client.connections.add(c);
12011 mServiceConnections.put(binder, c);
12012
12013 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
12014 s.lastActivity = SystemClock.uptimeMillis();
12015 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
12016 return 0;
12017 }
12018 }
12019
12020 if (s.app != null) {
12021 // This could have made the service more important.
12022 updateOomAdjLocked(s.app);
12023 }
12024
Joe Onorato8a9b2202010-02-26 18:56:32 -080012025 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012026 + ": received=" + b.intent.received
12027 + " apps=" + b.intent.apps.size()
12028 + " doRebind=" + b.intent.doRebind);
12029
12030 if (s.app != null && b.intent.received) {
12031 // Service is already running, so we can immediately
12032 // publish the connection.
12033 try {
12034 c.conn.connected(s.name, b.intent.binder);
12035 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012036 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012037 + " to connection " + c.conn.asBinder()
12038 + " (in " + c.binding.client.processName + ")", e);
12039 }
12040
12041 // If this is the first app connected back to this binding,
12042 // and the service had previously asked to be told when
12043 // rebound, then do so.
12044 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
12045 requestServiceBindingLocked(s, b.intent, true);
12046 }
12047 } else if (!b.intent.requested) {
12048 requestServiceBindingLocked(s, b.intent, false);
12049 }
12050
12051 Binder.restoreCallingIdentity(origId);
12052 }
12053
12054 return 1;
12055 }
12056
12057 private void removeConnectionLocked(
12058 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
12059 IBinder binder = c.conn.asBinder();
12060 AppBindRecord b = c.binding;
12061 ServiceRecord s = b.service;
12062 s.connections.remove(binder);
12063 b.connections.remove(c);
12064 if (c.activity != null && c.activity != skipAct) {
12065 if (c.activity.connections != null) {
12066 c.activity.connections.remove(c);
12067 }
12068 }
12069 if (b.client != skipApp) {
12070 b.client.connections.remove(c);
12071 }
12072 mServiceConnections.remove(binder);
12073
12074 if (b.connections.size() == 0) {
12075 b.intent.apps.remove(b.client);
12076 }
12077
Joe Onorato8a9b2202010-02-26 18:56:32 -080012078 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012079 + ": shouldUnbind=" + b.intent.hasBound);
12080 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
12081 && b.intent.hasBound) {
12082 try {
12083 bumpServiceExecutingLocked(s);
12084 updateOomAdjLocked(s.app);
12085 b.intent.hasBound = false;
12086 // Assume the client doesn't want to know about a rebind;
12087 // we will deal with that later if it asks for one.
12088 b.intent.doRebind = false;
12089 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
12090 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012091 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012092 serviceDoneExecutingLocked(s, true);
12093 }
12094 }
12095
12096 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
12097 bringDownServiceLocked(s, false);
12098 }
12099 }
12100
12101 public boolean unbindService(IServiceConnection connection) {
12102 synchronized (this) {
12103 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012104 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012105 ConnectionRecord r = mServiceConnections.get(binder);
12106 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012107 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012108 + connection.asBinder());
12109 return false;
12110 }
12111
12112 final long origId = Binder.clearCallingIdentity();
12113
12114 removeConnectionLocked(r, null, null);
12115
12116 if (r.binding.service.app != null) {
12117 // This could have made the service less important.
12118 updateOomAdjLocked(r.binding.service.app);
12119 }
12120
12121 Binder.restoreCallingIdentity(origId);
12122 }
12123
12124 return true;
12125 }
12126
12127 public void publishService(IBinder token, Intent intent, IBinder service) {
12128 // Refuse possible leaked file descriptors
12129 if (intent != null && intent.hasFileDescriptors() == true) {
12130 throw new IllegalArgumentException("File descriptors passed in Intent");
12131 }
12132
12133 synchronized(this) {
12134 if (!(token instanceof ServiceRecord)) {
12135 throw new IllegalArgumentException("Invalid service token");
12136 }
12137 ServiceRecord r = (ServiceRecord)token;
12138
12139 final long origId = Binder.clearCallingIdentity();
12140
Joe Onorato8a9b2202010-02-26 18:56:32 -080012141 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012142 + " " + intent + ": " + service);
12143 if (r != null) {
12144 Intent.FilterComparison filter
12145 = new Intent.FilterComparison(intent);
12146 IntentBindRecord b = r.bindings.get(filter);
12147 if (b != null && !b.received) {
12148 b.binder = service;
12149 b.requested = true;
12150 b.received = true;
12151 if (r.connections.size() > 0) {
12152 Iterator<ConnectionRecord> it
12153 = r.connections.values().iterator();
12154 while (it.hasNext()) {
12155 ConnectionRecord c = it.next();
12156 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012157 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012158 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012159 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012160 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012161 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012162 TAG, "Published intent: " + intent);
12163 continue;
12164 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012165 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012166 try {
12167 c.conn.connected(r.name, service);
12168 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012169 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012170 " to connection " + c.conn.asBinder() +
12171 " (in " + c.binding.client.processName + ")", e);
12172 }
12173 }
12174 }
12175 }
12176
12177 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12178
12179 Binder.restoreCallingIdentity(origId);
12180 }
12181 }
12182 }
12183
12184 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
12185 // Refuse possible leaked file descriptors
12186 if (intent != null && intent.hasFileDescriptors() == true) {
12187 throw new IllegalArgumentException("File descriptors passed in Intent");
12188 }
12189
12190 synchronized(this) {
12191 if (!(token instanceof ServiceRecord)) {
12192 throw new IllegalArgumentException("Invalid service token");
12193 }
12194 ServiceRecord r = (ServiceRecord)token;
12195
12196 final long origId = Binder.clearCallingIdentity();
12197
12198 if (r != null) {
12199 Intent.FilterComparison filter
12200 = new Intent.FilterComparison(intent);
12201 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012202 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012203 + " at " + b + ": apps="
12204 + (b != null ? b.apps.size() : 0));
12205 if (b != null) {
12206 if (b.apps.size() > 0) {
12207 // Applications have already bound since the last
12208 // unbind, so just rebind right here.
12209 requestServiceBindingLocked(r, b, true);
12210 } else {
12211 // Note to tell the service the next time there is
12212 // a new client.
12213 b.doRebind = true;
12214 }
12215 }
12216
12217 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12218
12219 Binder.restoreCallingIdentity(origId);
12220 }
12221 }
12222 }
12223
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012224 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012225 synchronized(this) {
12226 if (!(token instanceof ServiceRecord)) {
12227 throw new IllegalArgumentException("Invalid service token");
12228 }
12229 ServiceRecord r = (ServiceRecord)token;
12230 boolean inStopping = mStoppingServices.contains(token);
12231 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012232 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012233 + ": nesting=" + r.executeNesting
12234 + ", inStopping=" + inStopping);
12235 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012236 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012237 + " with incorrect token: given " + token
12238 + ", expected " + r);
12239 return;
12240 }
12241
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012242 if (type == 1) {
12243 // This is a call from a service start... take care of
12244 // book-keeping.
12245 r.callStart = true;
12246 switch (res) {
12247 case Service.START_STICKY_COMPATIBILITY:
12248 case Service.START_STICKY: {
12249 // We are done with the associated start arguments.
12250 r.findDeliveredStart(startId, true);
12251 // Don't stop if killed.
12252 r.stopIfKilled = false;
12253 break;
12254 }
12255 case Service.START_NOT_STICKY: {
12256 // We are done with the associated start arguments.
12257 r.findDeliveredStart(startId, true);
12258 if (r.lastStartId == startId) {
12259 // There is no more work, and this service
12260 // doesn't want to hang around if killed.
12261 r.stopIfKilled = true;
12262 }
12263 break;
12264 }
12265 case Service.START_REDELIVER_INTENT: {
12266 // We'll keep this item until they explicitly
12267 // call stop for it, but keep track of the fact
12268 // that it was delivered.
12269 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12270 if (si != null) {
12271 si.deliveryCount = 0;
12272 si.doneExecutingCount++;
12273 // Don't stop if killed.
12274 r.stopIfKilled = true;
12275 }
12276 break;
12277 }
12278 default:
12279 throw new IllegalArgumentException(
12280 "Unknown service start result: " + res);
12281 }
12282 if (res == Service.START_STICKY_COMPATIBILITY) {
12283 r.callStart = false;
12284 }
12285 }
12286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012287 final long origId = Binder.clearCallingIdentity();
12288 serviceDoneExecutingLocked(r, inStopping);
12289 Binder.restoreCallingIdentity(origId);
12290 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012291 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012292 + " with token " + token);
12293 }
12294 }
12295 }
12296
12297 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
12298 r.executeNesting--;
12299 if (r.executeNesting <= 0 && r.app != null) {
12300 r.app.executingServices.remove(r);
12301 if (r.app.executingServices.size() == 0) {
12302 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
12303 }
12304 if (inStopping) {
12305 mStoppingServices.remove(r);
12306 }
12307 updateOomAdjLocked(r.app);
12308 }
12309 }
12310
12311 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012312 String anrMessage = null;
12313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012314 synchronized(this) {
12315 if (proc.executingServices.size() == 0 || proc.thread == null) {
12316 return;
12317 }
12318 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12319 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12320 ServiceRecord timeout = null;
12321 long nextTime = 0;
12322 while (it.hasNext()) {
12323 ServiceRecord sr = it.next();
12324 if (sr.executingStart < maxTime) {
12325 timeout = sr;
12326 break;
12327 }
12328 if (sr.executingStart > nextTime) {
12329 nextTime = sr.executingStart;
12330 }
12331 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012332 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012333 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012334 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012335 } else {
12336 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12337 msg.obj = proc;
12338 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12339 }
12340 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012341
12342 if (anrMessage != null) {
12343 appNotResponding(proc, null, null, anrMessage);
12344 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012345 }
12346
12347 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012348 // BACKUP AND RESTORE
12349 // =========================================================
12350
12351 // Cause the target app to be launched if necessary and its backup agent
12352 // instantiated. The backup agent will invoke backupAgentCreated() on the
12353 // activity manager to announce its creation.
12354 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012355 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012356 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12357
12358 synchronized(this) {
12359 // !!! TODO: currently no check here that we're already bound
12360 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12361 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12362 synchronized (stats) {
12363 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12364 }
12365
12366 BackupRecord r = new BackupRecord(ss, app, backupMode);
12367 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12368 // startProcessLocked() returns existing proc's record if it's already running
12369 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012370 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012371 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012372 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012373 return false;
12374 }
12375
12376 r.app = proc;
12377 mBackupTarget = r;
12378 mBackupAppName = app.packageName;
12379
Christopher Tate6fa95972009-06-05 18:43:55 -070012380 // Try not to kill the process during backup
12381 updateOomAdjLocked(proc);
12382
Christopher Tate181fafa2009-05-14 11:12:14 -070012383 // If the process is already attached, schedule the creation of the backup agent now.
12384 // If it is not yet live, this will be done when it attaches to the framework.
12385 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012386 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012387 try {
12388 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12389 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012390 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012391 }
12392 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012393 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012394 }
12395 // Invariants: at this point, the target app process exists and the application
12396 // is either already running or in the process of coming up. mBackupTarget and
12397 // mBackupAppName describe the app, so that when it binds back to the AM we
12398 // know that it's scheduled for a backup-agent operation.
12399 }
12400
12401 return true;
12402 }
12403
12404 // A backup agent has just come up
12405 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012406 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012407 + " = " + agent);
12408
12409 synchronized(this) {
12410 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012411 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012412 return;
12413 }
12414
Christopher Tate043dadc2009-06-02 16:11:00 -070012415 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012416 try {
12417 IBackupManager bm = IBackupManager.Stub.asInterface(
12418 ServiceManager.getService(Context.BACKUP_SERVICE));
12419 bm.agentConnected(agentPackageName, agent);
12420 } catch (RemoteException e) {
12421 // can't happen; the backup manager service is local
12422 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012423 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012424 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012425 } finally {
12426 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012427 }
12428 }
12429 }
12430
12431 // done with this agent
12432 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012433 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012434 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012435 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012436 return;
12437 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012438
12439 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012440 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012441 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012442 return;
12443 }
12444
Christopher Tate181fafa2009-05-14 11:12:14 -070012445 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012446 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012447 return;
12448 }
12449
Christopher Tate6fa95972009-06-05 18:43:55 -070012450 ProcessRecord proc = mBackupTarget.app;
12451 mBackupTarget = null;
12452 mBackupAppName = null;
12453
12454 // Not backing this app up any more; reset its OOM adjustment
12455 updateOomAdjLocked(proc);
12456
Christopher Tatec7b31e32009-06-10 15:49:30 -070012457 // If the app crashed during backup, 'thread' will be null here
12458 if (proc.thread != null) {
12459 try {
12460 proc.thread.scheduleDestroyBackupAgent(appInfo);
12461 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012462 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012463 e.printStackTrace();
12464 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012465 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012466 }
12467 }
12468 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012469 // BROADCASTS
12470 // =========================================================
12471
Josh Bartel7f208742010-02-25 11:01:44 -060012472 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012473 List cur) {
12474 final ContentResolver resolver = mContext.getContentResolver();
12475 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12476 if (list == null) {
12477 return cur;
12478 }
12479 int N = list.size();
12480 for (int i=0; i<N; i++) {
12481 Intent intent = list.get(i);
12482 if (filter.match(resolver, intent, true, TAG) >= 0) {
12483 if (cur == null) {
12484 cur = new ArrayList<Intent>();
12485 }
12486 cur.add(intent);
12487 }
12488 }
12489 return cur;
12490 }
12491
12492 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012493 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012494 + mBroadcastsScheduled);
12495
12496 if (mBroadcastsScheduled) {
12497 return;
12498 }
12499 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12500 mBroadcastsScheduled = true;
12501 }
12502
12503 public Intent registerReceiver(IApplicationThread caller,
12504 IIntentReceiver receiver, IntentFilter filter, String permission) {
12505 synchronized(this) {
12506 ProcessRecord callerApp = null;
12507 if (caller != null) {
12508 callerApp = getRecordForAppLocked(caller);
12509 if (callerApp == null) {
12510 throw new SecurityException(
12511 "Unable to find app for caller " + caller
12512 + " (pid=" + Binder.getCallingPid()
12513 + ") when registering receiver " + receiver);
12514 }
12515 }
12516
12517 List allSticky = null;
12518
12519 // Look for any matching sticky broadcasts...
12520 Iterator actions = filter.actionsIterator();
12521 if (actions != null) {
12522 while (actions.hasNext()) {
12523 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012524 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012525 }
12526 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012527 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012528 }
12529
12530 // The first sticky in the list is returned directly back to
12531 // the client.
12532 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12533
Joe Onorato8a9b2202010-02-26 18:56:32 -080012534 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012535 + ": " + sticky);
12536
12537 if (receiver == null) {
12538 return sticky;
12539 }
12540
12541 ReceiverList rl
12542 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12543 if (rl == null) {
12544 rl = new ReceiverList(this, callerApp,
12545 Binder.getCallingPid(),
12546 Binder.getCallingUid(), receiver);
12547 if (rl.app != null) {
12548 rl.app.receivers.add(rl);
12549 } else {
12550 try {
12551 receiver.asBinder().linkToDeath(rl, 0);
12552 } catch (RemoteException e) {
12553 return sticky;
12554 }
12555 rl.linkedToDeath = true;
12556 }
12557 mRegisteredReceivers.put(receiver.asBinder(), rl);
12558 }
12559 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12560 rl.add(bf);
12561 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012562 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012563 }
12564 mReceiverResolver.addFilter(bf);
12565
12566 // Enqueue broadcasts for all existing stickies that match
12567 // this filter.
12568 if (allSticky != null) {
12569 ArrayList receivers = new ArrayList();
12570 receivers.add(bf);
12571
12572 int N = allSticky.size();
12573 for (int i=0; i<N; i++) {
12574 Intent intent = (Intent)allSticky.get(i);
12575 BroadcastRecord r = new BroadcastRecord(intent, null,
12576 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012577 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578 if (mParallelBroadcasts.size() == 0) {
12579 scheduleBroadcastsLocked();
12580 }
12581 mParallelBroadcasts.add(r);
12582 }
12583 }
12584
12585 return sticky;
12586 }
12587 }
12588
12589 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012590 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012591
12592 boolean doNext = false;
12593
12594 synchronized(this) {
12595 ReceiverList rl
12596 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12597 if (rl != null) {
12598 if (rl.curBroadcast != null) {
12599 BroadcastRecord r = rl.curBroadcast;
12600 doNext = finishReceiverLocked(
12601 receiver.asBinder(), r.resultCode, r.resultData,
12602 r.resultExtras, r.resultAbort, true);
12603 }
12604
12605 if (rl.app != null) {
12606 rl.app.receivers.remove(rl);
12607 }
12608 removeReceiverLocked(rl);
12609 if (rl.linkedToDeath) {
12610 rl.linkedToDeath = false;
12611 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12612 }
12613 }
12614 }
12615
12616 if (!doNext) {
12617 return;
12618 }
12619
12620 final long origId = Binder.clearCallingIdentity();
12621 processNextBroadcast(false);
12622 trimApplications();
12623 Binder.restoreCallingIdentity(origId);
12624 }
12625
12626 void removeReceiverLocked(ReceiverList rl) {
12627 mRegisteredReceivers.remove(rl.receiver.asBinder());
12628 int N = rl.size();
12629 for (int i=0; i<N; i++) {
12630 mReceiverResolver.removeFilter(rl.get(i));
12631 }
12632 }
12633
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012634 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12635 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12636 ProcessRecord r = mLruProcesses.get(i);
12637 if (r.thread != null) {
12638 try {
12639 r.thread.dispatchPackageBroadcast(cmd, packages);
12640 } catch (RemoteException ex) {
12641 }
12642 }
12643 }
12644 }
12645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012646 private final int broadcastIntentLocked(ProcessRecord callerApp,
12647 String callerPackage, Intent intent, String resolvedType,
12648 IIntentReceiver resultTo, int resultCode, String resultData,
12649 Bundle map, String requiredPermission,
12650 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12651 intent = new Intent(intent);
12652
Joe Onorato8a9b2202010-02-26 18:56:32 -080012653 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012654 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12655 + " ordered=" + ordered);
12656 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012657 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012658 }
12659
12660 // Handle special intents: if this broadcast is from the package
12661 // manager about a package being removed, we need to remove all of
12662 // its activities from the history stack.
12663 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12664 intent.getAction());
12665 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12666 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012667 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012668 || uidRemoved) {
12669 if (checkComponentPermission(
12670 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12671 callingPid, callingUid, -1)
12672 == PackageManager.PERMISSION_GRANTED) {
12673 if (uidRemoved) {
12674 final Bundle intentExtras = intent.getExtras();
12675 final int uid = intentExtras != null
12676 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12677 if (uid >= 0) {
12678 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12679 synchronized (bs) {
12680 bs.removeUidStatsLocked(uid);
12681 }
12682 }
12683 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012684 // If resources are unvailble just force stop all
12685 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012686 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012687 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12688 if (list != null && (list.length > 0)) {
12689 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012690 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012691 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012692 sendPackageBroadcastLocked(
12693 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012694 }
12695 } else {
12696 Uri data = intent.getData();
12697 String ssp;
12698 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12699 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12700 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012701 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012702 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012703 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
12704 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12705 new String[] {ssp});
12706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012707 }
12708 }
12709 }
12710 } else {
12711 String msg = "Permission Denial: " + intent.getAction()
12712 + " broadcast from " + callerPackage + " (pid=" + callingPid
12713 + ", uid=" + callingUid + ")"
12714 + " requires "
12715 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012716 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012717 throw new SecurityException(msg);
12718 }
12719 }
12720
12721 /*
12722 * If this is the time zone changed action, queue up a message that will reset the timezone
12723 * of all currently running processes. This message will get queued up before the broadcast
12724 * happens.
12725 */
12726 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12727 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12728 }
12729
Dianne Hackborn854060af2009-07-09 18:14:31 -070012730 /*
12731 * Prevent non-system code (defined here to be non-persistent
12732 * processes) from sending protected broadcasts.
12733 */
12734 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12735 || callingUid == Process.SHELL_UID || callingUid == 0) {
12736 // Always okay.
12737 } else if (callerApp == null || !callerApp.persistent) {
12738 try {
12739 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12740 intent.getAction())) {
12741 String msg = "Permission Denial: not allowed to send broadcast "
12742 + intent.getAction() + " from pid="
12743 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012744 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012745 throw new SecurityException(msg);
12746 }
12747 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012748 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012749 return BROADCAST_SUCCESS;
12750 }
12751 }
12752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012753 // Add to the sticky list if requested.
12754 if (sticky) {
12755 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12756 callingPid, callingUid)
12757 != PackageManager.PERMISSION_GRANTED) {
12758 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12759 + callingPid + ", uid=" + callingUid
12760 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012761 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012762 throw new SecurityException(msg);
12763 }
12764 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012765 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012766 + " and enforce permission " + requiredPermission);
12767 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12768 }
12769 if (intent.getComponent() != null) {
12770 throw new SecurityException(
12771 "Sticky broadcasts can't target a specific component");
12772 }
12773 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12774 if (list == null) {
12775 list = new ArrayList<Intent>();
12776 mStickyBroadcasts.put(intent.getAction(), list);
12777 }
12778 int N = list.size();
12779 int i;
12780 for (i=0; i<N; i++) {
12781 if (intent.filterEquals(list.get(i))) {
12782 // This sticky already exists, replace it.
12783 list.set(i, new Intent(intent));
12784 break;
12785 }
12786 }
12787 if (i >= N) {
12788 list.add(new Intent(intent));
12789 }
12790 }
12791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012792 // Figure out who all will receive this broadcast.
12793 List receivers = null;
12794 List<BroadcastFilter> registeredReceivers = null;
12795 try {
12796 if (intent.getComponent() != null) {
12797 // Broadcast is going to one specific receiver class...
12798 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012799 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012800 if (ai != null) {
12801 receivers = new ArrayList();
12802 ResolveInfo ri = new ResolveInfo();
12803 ri.activityInfo = ai;
12804 receivers.add(ri);
12805 }
12806 } else {
12807 // Need to resolve the intent to interested receivers...
12808 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12809 == 0) {
12810 receivers =
12811 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012812 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012813 }
Mihai Preda074edef2009-05-18 17:13:31 +020012814 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012815 }
12816 } catch (RemoteException ex) {
12817 // pm is in same process, this will never happen.
12818 }
12819
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012820 final boolean replacePending =
12821 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12822
Joe Onorato8a9b2202010-02-26 18:56:32 -080012823 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012824 + " replacePending=" + replacePending);
12825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012826 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12827 if (!ordered && NR > 0) {
12828 // If we are not serializing this broadcast, then send the
12829 // registered receivers separately so they don't wait for the
12830 // components to be launched.
12831 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12832 callerPackage, callingPid, callingUid, requiredPermission,
12833 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012834 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012835 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012836 TAG, "Enqueueing parallel broadcast " + r
12837 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012838 boolean replaced = false;
12839 if (replacePending) {
12840 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12841 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012842 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012843 "***** DROPPING PARALLEL: " + intent);
12844 mParallelBroadcasts.set(i, r);
12845 replaced = true;
12846 break;
12847 }
12848 }
12849 }
12850 if (!replaced) {
12851 mParallelBroadcasts.add(r);
12852 scheduleBroadcastsLocked();
12853 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012854 registeredReceivers = null;
12855 NR = 0;
12856 }
12857
12858 // Merge into one list.
12859 int ir = 0;
12860 if (receivers != null) {
12861 // A special case for PACKAGE_ADDED: do not allow the package
12862 // being added to see this broadcast. This prevents them from
12863 // using this as a back door to get run as soon as they are
12864 // installed. Maybe in the future we want to have a special install
12865 // broadcast or such for apps, but we'd like to deliberately make
12866 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012867 String skipPackages[] = null;
12868 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12869 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12870 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12871 Uri data = intent.getData();
12872 if (data != null) {
12873 String pkgName = data.getSchemeSpecificPart();
12874 if (pkgName != null) {
12875 skipPackages = new String[] { pkgName };
12876 }
12877 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012878 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012879 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012880 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012881 if (skipPackages != null && (skipPackages.length > 0)) {
12882 for (String skipPackage : skipPackages) {
12883 if (skipPackage != null) {
12884 int NT = receivers.size();
12885 for (int it=0; it<NT; it++) {
12886 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12887 if (curt.activityInfo.packageName.equals(skipPackage)) {
12888 receivers.remove(it);
12889 it--;
12890 NT--;
12891 }
12892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012893 }
12894 }
12895 }
12896
12897 int NT = receivers != null ? receivers.size() : 0;
12898 int it = 0;
12899 ResolveInfo curt = null;
12900 BroadcastFilter curr = null;
12901 while (it < NT && ir < NR) {
12902 if (curt == null) {
12903 curt = (ResolveInfo)receivers.get(it);
12904 }
12905 if (curr == null) {
12906 curr = registeredReceivers.get(ir);
12907 }
12908 if (curr.getPriority() >= curt.priority) {
12909 // Insert this broadcast record into the final list.
12910 receivers.add(it, curr);
12911 ir++;
12912 curr = null;
12913 it++;
12914 NT++;
12915 } else {
12916 // Skip to the next ResolveInfo in the final list.
12917 it++;
12918 curt = null;
12919 }
12920 }
12921 }
12922 while (ir < NR) {
12923 if (receivers == null) {
12924 receivers = new ArrayList();
12925 }
12926 receivers.add(registeredReceivers.get(ir));
12927 ir++;
12928 }
12929
12930 if ((receivers != null && receivers.size() > 0)
12931 || resultTo != null) {
12932 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12933 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012934 receivers, resultTo, resultCode, resultData, map, ordered,
12935 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012936 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012937 TAG, "Enqueueing ordered broadcast " + r
12938 + ": prev had " + mOrderedBroadcasts.size());
12939 if (DEBUG_BROADCAST) {
12940 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012941 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012942 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012943 boolean replaced = false;
12944 if (replacePending) {
12945 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12946 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012947 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012948 "***** DROPPING ORDERED: " + intent);
12949 mOrderedBroadcasts.set(i, r);
12950 replaced = true;
12951 break;
12952 }
12953 }
12954 }
12955 if (!replaced) {
12956 mOrderedBroadcasts.add(r);
12957 scheduleBroadcastsLocked();
12958 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012959 }
12960
12961 return BROADCAST_SUCCESS;
12962 }
12963
12964 public final int broadcastIntent(IApplicationThread caller,
12965 Intent intent, String resolvedType, IIntentReceiver resultTo,
12966 int resultCode, String resultData, Bundle map,
12967 String requiredPermission, boolean serialized, boolean sticky) {
12968 // Refuse possible leaked file descriptors
12969 if (intent != null && intent.hasFileDescriptors() == true) {
12970 throw new IllegalArgumentException("File descriptors passed in Intent");
12971 }
12972
12973 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012974 int flags = intent.getFlags();
12975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012976 if (!mSystemReady) {
12977 // if the caller really truly claims to know what they're doing, go
12978 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012979 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12980 intent = new Intent(intent);
12981 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12982 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012983 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012984 + " before boot completion");
12985 throw new IllegalStateException("Cannot broadcast before boot completed");
12986 }
12987 }
12988
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012989 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12990 throw new IllegalArgumentException(
12991 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12992 }
12993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012994 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12995 final int callingPid = Binder.getCallingPid();
12996 final int callingUid = Binder.getCallingUid();
12997 final long origId = Binder.clearCallingIdentity();
12998 int res = broadcastIntentLocked(callerApp,
12999 callerApp != null ? callerApp.info.packageName : null,
13000 intent, resolvedType, resultTo,
13001 resultCode, resultData, map, requiredPermission, serialized,
13002 sticky, callingPid, callingUid);
13003 Binder.restoreCallingIdentity(origId);
13004 return res;
13005 }
13006 }
13007
13008 int broadcastIntentInPackage(String packageName, int uid,
13009 Intent intent, String resolvedType, IIntentReceiver resultTo,
13010 int resultCode, String resultData, Bundle map,
13011 String requiredPermission, boolean serialized, boolean sticky) {
13012 synchronized(this) {
13013 final long origId = Binder.clearCallingIdentity();
13014 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
13015 resultTo, resultCode, resultData, map, requiredPermission,
13016 serialized, sticky, -1, uid);
13017 Binder.restoreCallingIdentity(origId);
13018 return res;
13019 }
13020 }
13021
13022 public final void unbroadcastIntent(IApplicationThread caller,
13023 Intent intent) {
13024 // Refuse possible leaked file descriptors
13025 if (intent != null && intent.hasFileDescriptors() == true) {
13026 throw new IllegalArgumentException("File descriptors passed in Intent");
13027 }
13028
13029 synchronized(this) {
13030 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
13031 != PackageManager.PERMISSION_GRANTED) {
13032 String msg = "Permission Denial: unbroadcastIntent() from pid="
13033 + Binder.getCallingPid()
13034 + ", uid=" + Binder.getCallingUid()
13035 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013036 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013037 throw new SecurityException(msg);
13038 }
13039 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
13040 if (list != null) {
13041 int N = list.size();
13042 int i;
13043 for (i=0; i<N; i++) {
13044 if (intent.filterEquals(list.get(i))) {
13045 list.remove(i);
13046 break;
13047 }
13048 }
13049 }
13050 }
13051 }
13052
13053 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
13054 String resultData, Bundle resultExtras, boolean resultAbort,
13055 boolean explicit) {
13056 if (mOrderedBroadcasts.size() == 0) {
13057 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013058 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013059 }
13060 return false;
13061 }
13062 BroadcastRecord r = mOrderedBroadcasts.get(0);
13063 if (r.receiver == null) {
13064 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013065 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013066 }
13067 return false;
13068 }
13069 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013070 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013071 return false;
13072 }
13073 int state = r.state;
13074 r.state = r.IDLE;
13075 if (state == r.IDLE) {
13076 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013077 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013078 }
13079 }
13080 r.receiver = null;
13081 r.intent.setComponent(null);
13082 if (r.curApp != null) {
13083 r.curApp.curReceiver = null;
13084 }
13085 if (r.curFilter != null) {
13086 r.curFilter.receiverList.curBroadcast = null;
13087 }
13088 r.curFilter = null;
13089 r.curApp = null;
13090 r.curComponent = null;
13091 r.curReceiver = null;
13092 mPendingBroadcast = null;
13093
13094 r.resultCode = resultCode;
13095 r.resultData = resultData;
13096 r.resultExtras = resultExtras;
13097 r.resultAbort = resultAbort;
13098
13099 // We will process the next receiver right now if this is finishing
13100 // an app receiver (which is always asynchronous) or after we have
13101 // come back from calling a receiver.
13102 return state == BroadcastRecord.APP_RECEIVE
13103 || state == BroadcastRecord.CALL_DONE_RECEIVE;
13104 }
13105
13106 public void finishReceiver(IBinder who, int resultCode, String resultData,
13107 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013108 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013109
13110 // Refuse possible leaked file descriptors
13111 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
13112 throw new IllegalArgumentException("File descriptors passed in Bundle");
13113 }
13114
13115 boolean doNext;
13116
13117 final long origId = Binder.clearCallingIdentity();
13118
13119 synchronized(this) {
13120 doNext = finishReceiverLocked(
13121 who, resultCode, resultData, resultExtras, resultAbort, true);
13122 }
13123
13124 if (doNext) {
13125 processNextBroadcast(false);
13126 }
13127 trimApplications();
13128
13129 Binder.restoreCallingIdentity(origId);
13130 }
13131
13132 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
13133 if (r.nextReceiver > 0) {
13134 Object curReceiver = r.receivers.get(r.nextReceiver-1);
13135 if (curReceiver instanceof BroadcastFilter) {
13136 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080013137 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013138 System.identityHashCode(r),
13139 r.intent.getAction(),
13140 r.nextReceiver - 1,
13141 System.identityHashCode(bf));
13142 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080013143 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013144 System.identityHashCode(r),
13145 r.intent.getAction(),
13146 r.nextReceiver - 1,
13147 ((ResolveInfo)curReceiver).toString());
13148 }
13149 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013150 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013151 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013152 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013153 System.identityHashCode(r),
13154 r.intent.getAction(),
13155 r.nextReceiver,
13156 "NONE");
13157 }
13158 }
13159
13160 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013161 ProcessRecord app = null;
13162 String anrMessage = null;
13163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013164 synchronized (this) {
13165 if (mOrderedBroadcasts.size() == 0) {
13166 return;
13167 }
13168 long now = SystemClock.uptimeMillis();
13169 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013170 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013171 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013172 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013173 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013174 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013175 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013176 return;
13177 }
13178
Joe Onorato8a9b2202010-02-26 18:56:32 -080013179 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013180 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013181 r.anrCount++;
13182
13183 // Current receiver has passed its expiration date.
13184 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013185 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013186 return;
13187 }
13188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013189 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013190 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013191 logBroadcastReceiverDiscard(r);
13192 if (curReceiver instanceof BroadcastFilter) {
13193 BroadcastFilter bf = (BroadcastFilter)curReceiver;
13194 if (bf.receiverList.pid != 0
13195 && bf.receiverList.pid != MY_PID) {
13196 synchronized (this.mPidsSelfLocked) {
13197 app = this.mPidsSelfLocked.get(
13198 bf.receiverList.pid);
13199 }
13200 }
13201 } else {
13202 app = r.curApp;
13203 }
13204
13205 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013206 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013207 }
13208
13209 if (mPendingBroadcast == r) {
13210 mPendingBroadcast = null;
13211 }
13212
13213 // Move on to the next receiver.
13214 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13215 r.resultExtras, r.resultAbort, true);
13216 scheduleBroadcastsLocked();
13217 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013218
13219 if (anrMessage != null) {
13220 appNotResponding(app, null, null, anrMessage);
13221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013222 }
13223
13224 private final void processCurBroadcastLocked(BroadcastRecord r,
13225 ProcessRecord app) throws RemoteException {
13226 if (app.thread == null) {
13227 throw new RemoteException();
13228 }
13229 r.receiver = app.thread.asBinder();
13230 r.curApp = app;
13231 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013232 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013233
13234 // Tell the application to launch this receiver.
13235 r.intent.setComponent(r.curComponent);
13236
13237 boolean started = false;
13238 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013239 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013240 "Delivering to component " + r.curComponent
13241 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070013242 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013243 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
13244 r.resultCode, r.resultData, r.resultExtras, r.ordered);
13245 started = true;
13246 } finally {
13247 if (!started) {
13248 r.receiver = null;
13249 r.curApp = null;
13250 app.curReceiver = null;
13251 }
13252 }
13253
13254 }
13255
13256 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013257 Intent intent, int resultCode, String data, Bundle extras,
13258 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013259 if (app != null && app.thread != null) {
13260 // If we have an app thread, do the call through that so it is
13261 // correctly ordered with other one-way calls.
13262 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013263 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013264 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013265 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013266 }
13267 }
13268
13269 private final void deliverToRegisteredReceiver(BroadcastRecord r,
13270 BroadcastFilter filter, boolean ordered) {
13271 boolean skip = false;
13272 if (filter.requiredPermission != null) {
13273 int perm = checkComponentPermission(filter.requiredPermission,
13274 r.callingPid, r.callingUid, -1);
13275 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013276 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013277 + r.intent.toString()
13278 + " from " + r.callerPackage + " (pid="
13279 + r.callingPid + ", uid=" + r.callingUid + ")"
13280 + " requires " + filter.requiredPermission
13281 + " due to registered receiver " + filter);
13282 skip = true;
13283 }
13284 }
13285 if (r.requiredPermission != null) {
13286 int perm = checkComponentPermission(r.requiredPermission,
13287 filter.receiverList.pid, filter.receiverList.uid, -1);
13288 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013289 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013290 + r.intent.toString()
13291 + " to " + filter.receiverList.app
13292 + " (pid=" + filter.receiverList.pid
13293 + ", uid=" + filter.receiverList.uid + ")"
13294 + " requires " + r.requiredPermission
13295 + " due to sender " + r.callerPackage
13296 + " (uid " + r.callingUid + ")");
13297 skip = true;
13298 }
13299 }
13300
13301 if (!skip) {
13302 // If this is not being sent as an ordered broadcast, then we
13303 // don't want to touch the fields that keep track of the current
13304 // state of ordered broadcasts.
13305 if (ordered) {
13306 r.receiver = filter.receiverList.receiver.asBinder();
13307 r.curFilter = filter;
13308 filter.receiverList.curBroadcast = r;
13309 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013310 if (filter.receiverList.app != null) {
13311 // Bump hosting application to no longer be in background
13312 // scheduling class. Note that we can't do that if there
13313 // isn't an app... but we can only be in that case for
13314 // things that directly call the IActivityManager API, which
13315 // are already core system stuff so don't matter for this.
13316 r.curApp = filter.receiverList.app;
13317 filter.receiverList.app.curReceiver = r;
13318 updateOomAdjLocked();
13319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013320 }
13321 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013322 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013323 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013324 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013325 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013326 }
13327 performReceive(filter.receiverList.app, filter.receiverList.receiver,
13328 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013329 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013330 if (ordered) {
13331 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13332 }
13333 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013334 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013335 if (ordered) {
13336 r.receiver = null;
13337 r.curFilter = null;
13338 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013339 if (filter.receiverList.app != null) {
13340 filter.receiverList.app.curReceiver = null;
13341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013342 }
13343 }
13344 }
13345 }
13346
Dianne Hackborn12527f92009-11-11 17:39:50 -080013347 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13348 if (r.callingUid < 0) {
13349 // This was from a registerReceiver() call; ignore it.
13350 return;
13351 }
13352 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13353 MAX_BROADCAST_HISTORY-1);
13354 r.finishTime = SystemClock.uptimeMillis();
13355 mBroadcastHistory[0] = r;
13356 }
13357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013358 private final void processNextBroadcast(boolean fromMsg) {
13359 synchronized(this) {
13360 BroadcastRecord r;
13361
Joe Onorato8a9b2202010-02-26 18:56:32 -080013362 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013363 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013364 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013365
13366 updateCpuStats();
13367
13368 if (fromMsg) {
13369 mBroadcastsScheduled = false;
13370 }
13371
13372 // First, deliver any non-serialized broadcasts right away.
13373 while (mParallelBroadcasts.size() > 0) {
13374 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013375 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013376 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013377 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013378 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013379 for (int i=0; i<N; i++) {
13380 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013381 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013382 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013383 + target + ": " + r);
13384 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13385 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013386 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013387 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013388 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013389 }
13390
13391 // Now take care of the next serialized one...
13392
13393 // If we are waiting for a process to come up to handle the next
13394 // broadcast, then do nothing at this point. Just in case, we
13395 // check that the process we're waiting for still exists.
13396 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013397 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013398 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013399 + mPendingBroadcast.curApp);
13400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013401
13402 boolean isDead;
13403 synchronized (mPidsSelfLocked) {
13404 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13405 }
13406 if (!isDead) {
13407 // It's still alive, so keep waiting
13408 return;
13409 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013410 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013411 + " died before responding to broadcast");
13412 mPendingBroadcast = null;
13413 }
13414 }
13415
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013416 boolean looped = false;
13417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013418 do {
13419 if (mOrderedBroadcasts.size() == 0) {
13420 // No more broadcasts pending, so all done!
13421 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013422 if (looped) {
13423 // If we had finished the last ordered broadcast, then
13424 // make sure all processes have correct oom and sched
13425 // adjustments.
13426 updateOomAdjLocked();
13427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013428 return;
13429 }
13430 r = mOrderedBroadcasts.get(0);
13431 boolean forceReceive = false;
13432
13433 // Ensure that even if something goes awry with the timeout
13434 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013435 // and continue to make progress.
13436 //
13437 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
13438 // receivers don't get executed with with timeouts. They're intended for
13439 // one time heavy lifting after system upgrades and can take
13440 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013441 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013442 if (mSystemReady && r.dispatchTime > 0) {
13443 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013444 if ((numReceivers > 0) &&
13445 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013446 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013447 + " now=" + now
13448 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013449 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013450 + " intent=" + r.intent
13451 + " numReceivers=" + numReceivers
13452 + " nextReceiver=" + r.nextReceiver
13453 + " state=" + r.state);
13454 broadcastTimeout(); // forcibly finish this broadcast
13455 forceReceive = true;
13456 r.state = BroadcastRecord.IDLE;
13457 }
13458 }
13459
13460 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013461 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013462 "processNextBroadcast() called when not idle (state="
13463 + r.state + ")");
13464 return;
13465 }
13466
13467 if (r.receivers == null || r.nextReceiver >= numReceivers
13468 || r.resultAbort || forceReceive) {
13469 // No more receivers for this broadcast! Send the final
13470 // result if requested...
13471 if (r.resultTo != null) {
13472 try {
13473 if (DEBUG_BROADCAST) {
13474 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013475 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013476 + " seq=" + seq + " app=" + r.callerApp);
13477 }
13478 performReceive(r.callerApp, r.resultTo,
13479 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013480 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013481 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013482 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013483 }
13484 }
13485
Joe Onorato8a9b2202010-02-26 18:56:32 -080013486 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013487 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13488
Joe Onorato8a9b2202010-02-26 18:56:32 -080013489 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013490 + r);
13491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013492 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013493 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013494 mOrderedBroadcasts.remove(0);
13495 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013496 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013497 continue;
13498 }
13499 } while (r == null);
13500
13501 // Get the next receiver...
13502 int recIdx = r.nextReceiver++;
13503
13504 // Keep track of when this receiver started, and make sure there
13505 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013506 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013507 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013508 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013509
Joe Onorato8a9b2202010-02-26 18:56:32 -080013510 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013511 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013512 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013513 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013514 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013515 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013516 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013517 }
13518
13519 Object nextReceiver = r.receivers.get(recIdx);
13520 if (nextReceiver instanceof BroadcastFilter) {
13521 // Simple case: this is a registered receiver who gets
13522 // a direct call.
13523 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013524 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013525 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013526 + filter + ": " + r);
13527 deliverToRegisteredReceiver(r, filter, r.ordered);
13528 if (r.receiver == null || !r.ordered) {
13529 // The receiver has already finished, so schedule to
13530 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013531 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13532 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013533 r.state = BroadcastRecord.IDLE;
13534 scheduleBroadcastsLocked();
13535 }
13536 return;
13537 }
13538
13539 // Hard case: need to instantiate the receiver, possibly
13540 // starting its application process to host it.
13541
13542 ResolveInfo info =
13543 (ResolveInfo)nextReceiver;
13544
13545 boolean skip = false;
13546 int perm = checkComponentPermission(info.activityInfo.permission,
13547 r.callingPid, r.callingUid,
13548 info.activityInfo.exported
13549 ? -1 : info.activityInfo.applicationInfo.uid);
13550 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013551 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013552 + r.intent.toString()
13553 + " from " + r.callerPackage + " (pid=" + r.callingPid
13554 + ", uid=" + r.callingUid + ")"
13555 + " requires " + info.activityInfo.permission
13556 + " due to receiver " + info.activityInfo.packageName
13557 + "/" + info.activityInfo.name);
13558 skip = true;
13559 }
13560 if (r.callingUid != Process.SYSTEM_UID &&
13561 r.requiredPermission != null) {
13562 try {
13563 perm = ActivityThread.getPackageManager().
13564 checkPermission(r.requiredPermission,
13565 info.activityInfo.applicationInfo.packageName);
13566 } catch (RemoteException e) {
13567 perm = PackageManager.PERMISSION_DENIED;
13568 }
13569 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013570 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013571 + r.intent + " to "
13572 + info.activityInfo.applicationInfo.packageName
13573 + " requires " + r.requiredPermission
13574 + " due to sender " + r.callerPackage
13575 + " (uid " + r.callingUid + ")");
13576 skip = true;
13577 }
13578 }
13579 if (r.curApp != null && r.curApp.crashing) {
13580 // If the target process is crashing, just skip it.
13581 skip = true;
13582 }
13583
13584 if (skip) {
13585 r.receiver = null;
13586 r.curFilter = null;
13587 r.state = BroadcastRecord.IDLE;
13588 scheduleBroadcastsLocked();
13589 return;
13590 }
13591
13592 r.state = BroadcastRecord.APP_RECEIVE;
13593 String targetProcess = info.activityInfo.processName;
13594 r.curComponent = new ComponentName(
13595 info.activityInfo.applicationInfo.packageName,
13596 info.activityInfo.name);
13597 r.curReceiver = info.activityInfo;
13598
13599 // Is this receiver's application already running?
13600 ProcessRecord app = getProcessRecordLocked(targetProcess,
13601 info.activityInfo.applicationInfo.uid);
13602 if (app != null && app.thread != null) {
13603 try {
13604 processCurBroadcastLocked(r, app);
13605 return;
13606 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013607 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013608 + r.curComponent, e);
13609 }
13610
13611 // If a dead object exception was thrown -- fall through to
13612 // restart the application.
13613 }
13614
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013615 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013616 if ((r.curApp=startProcessLocked(targetProcess,
13617 info.activityInfo.applicationInfo, true,
13618 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013619 "broadcast", r.curComponent,
13620 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13621 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013622 // Ah, this recipient is unavailable. Finish it if necessary,
13623 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013624 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013625 + info.activityInfo.applicationInfo.packageName + "/"
13626 + info.activityInfo.applicationInfo.uid + " for broadcast "
13627 + r.intent + ": process is bad");
13628 logBroadcastReceiverDiscard(r);
13629 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13630 r.resultExtras, r.resultAbort, true);
13631 scheduleBroadcastsLocked();
13632 r.state = BroadcastRecord.IDLE;
13633 return;
13634 }
13635
13636 mPendingBroadcast = r;
13637 }
13638 }
13639
13640 // =========================================================
13641 // INSTRUMENTATION
13642 // =========================================================
13643
13644 public boolean startInstrumentation(ComponentName className,
13645 String profileFile, int flags, Bundle arguments,
13646 IInstrumentationWatcher watcher) {
13647 // Refuse possible leaked file descriptors
13648 if (arguments != null && arguments.hasFileDescriptors()) {
13649 throw new IllegalArgumentException("File descriptors passed in Bundle");
13650 }
13651
13652 synchronized(this) {
13653 InstrumentationInfo ii = null;
13654 ApplicationInfo ai = null;
13655 try {
13656 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013657 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013658 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013659 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013660 } catch (PackageManager.NameNotFoundException e) {
13661 }
13662 if (ii == null) {
13663 reportStartInstrumentationFailure(watcher, className,
13664 "Unable to find instrumentation info for: " + className);
13665 return false;
13666 }
13667 if (ai == null) {
13668 reportStartInstrumentationFailure(watcher, className,
13669 "Unable to find instrumentation target package: " + ii.targetPackage);
13670 return false;
13671 }
13672
13673 int match = mContext.getPackageManager().checkSignatures(
13674 ii.targetPackage, ii.packageName);
13675 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13676 String msg = "Permission Denial: starting instrumentation "
13677 + className + " from pid="
13678 + Binder.getCallingPid()
13679 + ", uid=" + Binder.getCallingPid()
13680 + " not allowed because package " + ii.packageName
13681 + " does not have a signature matching the target "
13682 + ii.targetPackage;
13683 reportStartInstrumentationFailure(watcher, className, msg);
13684 throw new SecurityException(msg);
13685 }
13686
13687 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013688 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013689 ProcessRecord app = addAppLocked(ai);
13690 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013691 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013692 app.instrumentationProfileFile = profileFile;
13693 app.instrumentationArguments = arguments;
13694 app.instrumentationWatcher = watcher;
13695 app.instrumentationResultClass = className;
13696 Binder.restoreCallingIdentity(origId);
13697 }
13698
13699 return true;
13700 }
13701
13702 /**
13703 * Report errors that occur while attempting to start Instrumentation. Always writes the
13704 * error to the logs, but if somebody is watching, send the report there too. This enables
13705 * the "am" command to report errors with more information.
13706 *
13707 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13708 * @param cn The component name of the instrumentation.
13709 * @param report The error report.
13710 */
13711 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13712 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013713 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013714 try {
13715 if (watcher != null) {
13716 Bundle results = new Bundle();
13717 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13718 results.putString("Error", report);
13719 watcher.instrumentationStatus(cn, -1, results);
13720 }
13721 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013722 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013723 }
13724 }
13725
13726 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13727 if (app.instrumentationWatcher != null) {
13728 try {
13729 // NOTE: IInstrumentationWatcher *must* be oneway here
13730 app.instrumentationWatcher.instrumentationFinished(
13731 app.instrumentationClass,
13732 resultCode,
13733 results);
13734 } catch (RemoteException e) {
13735 }
13736 }
13737 app.instrumentationWatcher = null;
13738 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013739 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013740 app.instrumentationProfileFile = null;
13741 app.instrumentationArguments = null;
13742
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013743 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013744 }
13745
13746 public void finishInstrumentation(IApplicationThread target,
13747 int resultCode, Bundle results) {
13748 // Refuse possible leaked file descriptors
13749 if (results != null && results.hasFileDescriptors()) {
13750 throw new IllegalArgumentException("File descriptors passed in Intent");
13751 }
13752
13753 synchronized(this) {
13754 ProcessRecord app = getRecordForAppLocked(target);
13755 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013756 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013757 return;
13758 }
13759 final long origId = Binder.clearCallingIdentity();
13760 finishInstrumentationLocked(app, resultCode, results);
13761 Binder.restoreCallingIdentity(origId);
13762 }
13763 }
13764
13765 // =========================================================
13766 // CONFIGURATION
13767 // =========================================================
13768
13769 public ConfigurationInfo getDeviceConfigurationInfo() {
13770 ConfigurationInfo config = new ConfigurationInfo();
13771 synchronized (this) {
13772 config.reqTouchScreen = mConfiguration.touchscreen;
13773 config.reqKeyboardType = mConfiguration.keyboard;
13774 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013775 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13776 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013777 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13778 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013779 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13780 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013781 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13782 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013783 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013784 }
13785 return config;
13786 }
13787
13788 public Configuration getConfiguration() {
13789 Configuration ci;
13790 synchronized(this) {
13791 ci = new Configuration(mConfiguration);
13792 }
13793 return ci;
13794 }
13795
13796 public void updateConfiguration(Configuration values) {
13797 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13798 "updateConfiguration()");
13799
13800 synchronized(this) {
13801 if (values == null && mWindowManager != null) {
13802 // sentinel: fetch the current configuration from the window manager
13803 values = mWindowManager.computeNewConfiguration();
13804 }
13805
13806 final long origId = Binder.clearCallingIdentity();
13807 updateConfigurationLocked(values, null);
13808 Binder.restoreCallingIdentity(origId);
13809 }
13810 }
13811
13812 /**
13813 * Do either or both things: (1) change the current configuration, and (2)
13814 * make sure the given activity is running with the (now) current
13815 * configuration. Returns true if the activity has been left running, or
13816 * false if <var>starting</var> is being destroyed to match the new
13817 * configuration.
13818 */
13819 public boolean updateConfigurationLocked(Configuration values,
13820 HistoryRecord starting) {
13821 int changes = 0;
13822
13823 boolean kept = true;
13824
13825 if (values != null) {
13826 Configuration newConfig = new Configuration(mConfiguration);
13827 changes = newConfig.updateFrom(values);
13828 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013829 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013830 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013831 }
13832
Doug Zongker2bec3d42009-12-04 12:52:44 -080013833 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013834
13835 if (values.locale != null) {
13836 saveLocaleLocked(values.locale,
13837 !values.locale.equals(mConfiguration.locale),
13838 values.userSetLocale);
13839 }
13840
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013841 mConfigurationSeq++;
13842 if (mConfigurationSeq <= 0) {
13843 mConfigurationSeq = 1;
13844 }
13845 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013846 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013847 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013848
13849 AttributeCache ac = AttributeCache.instance();
13850 if (ac != null) {
13851 ac.updateConfiguration(mConfiguration);
13852 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013853
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013854 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13855 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13856 msg.obj = new Configuration(mConfiguration);
13857 mHandler.sendMessage(msg);
13858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013859
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013860 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13861 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013862 try {
13863 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013864 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013865 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013866 app.thread.scheduleConfigurationChanged(mConfiguration);
13867 }
13868 } catch (Exception e) {
13869 }
13870 }
13871 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013872 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13873 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013874 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13875 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013876 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13877 broadcastIntentLocked(null, null,
13878 new Intent(Intent.ACTION_LOCALE_CHANGED),
13879 null, null, 0, null, null,
13880 null, false, false, MY_PID, Process.SYSTEM_UID);
13881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013882 }
13883 }
13884
13885 if (changes != 0 && starting == null) {
13886 // If the configuration changed, and the caller is not already
13887 // in the process of starting an activity, then find the top
13888 // activity to check if its configuration needs to change.
13889 starting = topRunningActivityLocked(null);
13890 }
13891
13892 if (starting != null) {
13893 kept = ensureActivityConfigurationLocked(starting, changes);
13894 if (kept) {
13895 // If this didn't result in the starting activity being
13896 // destroyed, then we need to make sure at this point that all
13897 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013898 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013899 + ", ensuring others are correct.");
13900 ensureActivitiesVisibleLocked(starting, changes);
13901 }
13902 }
13903
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013904 if (values != null && mWindowManager != null) {
13905 mWindowManager.setNewConfiguration(mConfiguration);
13906 }
13907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013908 return kept;
13909 }
13910
13911 private final boolean relaunchActivityLocked(HistoryRecord r,
13912 int changes, boolean andResume) {
13913 List<ResultInfo> results = null;
13914 List<Intent> newIntents = null;
13915 if (andResume) {
13916 results = r.results;
13917 newIntents = r.newIntents;
13918 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013919 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013920 + " with results=" + results + " newIntents=" + newIntents
13921 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013922 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13923 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013924 r.task.taskId, r.shortComponentName);
13925
13926 r.startFreezingScreenLocked(r.app, 0);
13927
13928 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013929 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013930 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013931 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013932 // Note: don't need to call pauseIfSleepingLocked() here, because
13933 // the caller will only pass in 'andResume' if this activity is
13934 // currently resumed, which implies we aren't sleeping.
13935 } catch (RemoteException e) {
13936 return false;
13937 }
13938
13939 if (andResume) {
13940 r.results = null;
13941 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013942 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013943 }
13944
13945 return true;
13946 }
13947
13948 /**
13949 * Make sure the given activity matches the current configuration. Returns
13950 * false if the activity had to be destroyed. Returns true if the
13951 * configuration is the same, or the activity will remain running as-is
13952 * for whatever reason. Ensures the HistoryRecord is updated with the
13953 * correct configuration and all other bookkeeping is handled.
13954 */
13955 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13956 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070013957 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013958 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13959 "Skipping config check (will change): " + r);
13960 return true;
13961 }
13962
Joe Onorato8a9b2202010-02-26 18:56:32 -080013963 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013964 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013965
13966 // Short circuit: if the two configurations are the exact same
13967 // object (the common case), then there is nothing to do.
13968 Configuration newConfig = mConfiguration;
13969 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013970 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013971 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013972 return true;
13973 }
13974
13975 // We don't worry about activities that are finishing.
13976 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013977 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013978 "Configuration doesn't matter in finishing " + r);
13979 r.stopFreezingScreenLocked(false);
13980 return true;
13981 }
13982
13983 // Okay we now are going to make this activity have the new config.
13984 // But then we need to figure out how it needs to deal with that.
13985 Configuration oldConfig = r.configuration;
13986 r.configuration = newConfig;
13987
13988 // If the activity isn't currently running, just leave the new
13989 // configuration and it will pick that up next time it starts.
13990 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013991 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013992 "Configuration doesn't matter not running " + r);
13993 r.stopFreezingScreenLocked(false);
13994 return true;
13995 }
13996
13997 // If the activity isn't persistent, there is a chance we will
13998 // need to restart it.
13999 if (!r.persistent) {
14000
14001 // Figure out what has changed between the two configurations.
14002 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014003 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014004 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014005 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014006 + Integer.toHexString(r.info.configChanges)
14007 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014008 }
14009 if ((changes&(~r.info.configChanges)) != 0) {
14010 // Aha, the activity isn't handling the change, so DIE DIE DIE.
14011 r.configChangeFlags |= changes;
14012 r.startFreezingScreenLocked(r.app, globalChanges);
14013 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014014 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014015 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014016 destroyActivityLocked(r, true);
14017 } else if (r.state == ActivityState.PAUSING) {
14018 // A little annoying: we are waiting for this activity to
14019 // finish pausing. Let's not do anything now, but just
14020 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014021 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014022 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014023 r.configDestroy = true;
14024 return true;
14025 } else if (r.state == ActivityState.RESUMED) {
14026 // Try to optimize this case: the configuration is changing
14027 // and we need to restart the top, resumed activity.
14028 // Instead of doing the normal handshaking, just say
14029 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080014030 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014031 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014032 relaunchActivityLocked(r, r.configChangeFlags, true);
14033 r.configChangeFlags = 0;
14034 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014035 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014036 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014037 relaunchActivityLocked(r, r.configChangeFlags, false);
14038 r.configChangeFlags = 0;
14039 }
14040
14041 // All done... tell the caller we weren't able to keep this
14042 // activity around.
14043 return false;
14044 }
14045 }
14046
14047 // Default case: the activity can handle this new configuration, so
14048 // hand it over. Note that we don't need to give it the new
14049 // configuration, since we always send configuration changes to all
14050 // process when they happen so it can just use whatever configuration
14051 // it last got.
14052 if (r.app != null && r.app.thread != null) {
14053 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014054 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014055 r.app.thread.scheduleActivityConfigurationChanged(r);
14056 } catch (RemoteException e) {
14057 // If process died, whatever.
14058 }
14059 }
14060 r.stopFreezingScreenLocked(false);
14061
14062 return true;
14063 }
14064
14065 /**
14066 * Save the locale. You must be inside a synchronized (this) block.
14067 */
14068 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
14069 if(isDiff) {
14070 SystemProperties.set("user.language", l.getLanguage());
14071 SystemProperties.set("user.region", l.getCountry());
14072 }
14073
14074 if(isPersist) {
14075 SystemProperties.set("persist.sys.language", l.getLanguage());
14076 SystemProperties.set("persist.sys.country", l.getCountry());
14077 SystemProperties.set("persist.sys.localevar", l.getVariant());
14078 }
14079 }
14080
14081 // =========================================================
14082 // LIFETIME MANAGEMENT
14083 // =========================================================
14084
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014085 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
14086 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014087 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014088 // This adjustment has already been computed. If we are calling
14089 // from the top, we may have already computed our adjustment with
14090 // an earlier hidden adjustment that isn't really for us... if
14091 // so, use the new hidden adjustment.
14092 if (!recursed && app.hidden) {
14093 app.curAdj = hiddenAdj;
14094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014095 return app.curAdj;
14096 }
14097
14098 if (app.thread == null) {
14099 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014100 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014101 return (app.curAdj=EMPTY_APP_ADJ);
14102 }
14103
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014104 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
14105 // The max adjustment doesn't allow this app to be anything
14106 // below foreground, so it is not worth doing work for it.
14107 app.adjType = "fixed";
14108 app.adjSeq = mAdjSeq;
14109 app.curRawAdj = app.maxAdj;
14110 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
14111 return (app.curAdj=app.maxAdj);
14112 }
14113
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014114 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014115 app.adjSource = null;
14116 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014117 app.empty = false;
14118 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014119
The Android Open Source Project4df24232009-03-05 14:34:35 -080014120 // Determine the importance of the process, starting with most
14121 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014122 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014123 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014124 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014125 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014126 // The last app on the list is the foreground app.
14127 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014128 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014129 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014130 } else if (app.instrumentationClass != null) {
14131 // Don't want to kill running instrumentation.
14132 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014133 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014134 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014135 } else if (app.persistentActivities > 0) {
14136 // Special persistent activities... shouldn't be used these days.
14137 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014138 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014139 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014140 } else if (app.curReceiver != null ||
14141 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
14142 // An app that is currently receiving a broadcast also
14143 // counts as being in the foreground.
14144 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014145 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014146 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014147 } else if (app.executingServices.size() > 0) {
14148 // An app that is currently executing a service callback also
14149 // counts as being in the foreground.
14150 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014151 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014152 app.adjType = "exec-service";
14153 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014154 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014155 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014156 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014157 app.adjType = "foreground-service";
14158 } else if (app.forcingToForeground != null) {
14159 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014160 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014161 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014162 app.adjType = "force-foreground";
14163 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014164 } else if (app == mHeavyWeightProcess) {
14165 // We don't want to kill the current heavy-weight process.
14166 adj = HEAVY_WEIGHT_APP_ADJ;
14167 schedGroup = Process.THREAD_GROUP_DEFAULT;
14168 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080014169 } else if (app == mHomeProcess) {
14170 // This process is hosting what we currently consider to be the
14171 // home app, so we don't want to let it go into the background.
14172 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014173 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014174 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014175 } else if ((N=app.activities.size()) != 0) {
14176 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014177 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014178 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014179 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014180 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014181 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014182 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014183 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014184 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014185 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014186 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014187 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014188 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014189 break;
14190 }
14191 }
14192 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014193 // A very not-needed process. If this is lower in the lru list,
14194 // we will push it in to the empty bucket.
14195 app.hidden = true;
14196 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014197 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014198 adj = hiddenAdj;
14199 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014200 }
14201
Joe Onorato8a9b2202010-02-26 18:56:32 -080014202 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014203
The Android Open Source Project4df24232009-03-05 14:34:35 -080014204 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014205 // there are applications dependent on our services or providers, but
14206 // this gives us a baseline and makes sure we don't get into an
14207 // infinite recursion.
14208 app.adjSeq = mAdjSeq;
14209 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014210
Christopher Tate6fa95972009-06-05 18:43:55 -070014211 if (mBackupTarget != null && app == mBackupTarget.app) {
14212 // If possible we want to avoid killing apps while they're being backed up
14213 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014214 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070014215 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014216 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014217 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070014218 }
14219 }
14220
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014221 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
14222 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014223 final long now = SystemClock.uptimeMillis();
14224 // This process is more important if the top activity is
14225 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070014226 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014227 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014228 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014229 if (s.startRequested) {
14230 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14231 // This service has seen some activity within
14232 // recent memory, so we will keep its process ahead
14233 // of the background processes.
14234 if (adj > SECONDARY_SERVER_ADJ) {
14235 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014236 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014237 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014238 }
14239 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014240 // If we have let the service slide into the background
14241 // state, still have some text describing what it is doing
14242 // even though the service no longer has an impact.
14243 if (adj > SECONDARY_SERVER_ADJ) {
14244 app.adjType = "started-bg-services";
14245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014246 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014247 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
14248 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014249 Iterator<ConnectionRecord> kt
14250 = s.connections.values().iterator();
14251 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14252 // XXX should compute this based on the max of
14253 // all connected clients.
14254 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014255 if (cr.binding.client == app) {
14256 // Binding to ourself is not interesting.
14257 continue;
14258 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014259 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
14260 ProcessRecord client = cr.binding.client;
14261 int myHiddenAdj = hiddenAdj;
14262 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014263 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014264 myHiddenAdj = client.hiddenAdj;
14265 } else {
14266 myHiddenAdj = VISIBLE_APP_ADJ;
14267 }
14268 }
14269 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014270 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014271 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014272 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014273 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014274 if (!client.hidden) {
14275 app.hidden = false;
14276 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014277 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014278 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14279 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014280 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014281 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014282 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014283 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14284 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14285 schedGroup = Process.THREAD_GROUP_DEFAULT;
14286 }
14287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014288 }
14289 HistoryRecord a = cr.activity;
14290 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014291 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014292 //}
14293 if (a != null && adj > FOREGROUND_APP_ADJ &&
14294 (a.state == ActivityState.RESUMED
14295 || a.state == ActivityState.PAUSING)) {
14296 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014297 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014298 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014299 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014300 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14301 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014302 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014303 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014304 }
14305 }
14306 }
14307 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014308
14309 // Finally, f this process has active services running in it, we
14310 // would like to avoid killing it unless it would prevent the current
14311 // application from running. By default we put the process in
14312 // with the rest of the background processes; as we scan through
14313 // its services we may bump it up from there.
14314 if (adj > hiddenAdj) {
14315 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014316 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014317 app.adjType = "bg-services";
14318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014319 }
14320
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014321 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
14322 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014323 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014324 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
14325 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014326 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014327 if (cpr.clients.size() != 0) {
14328 Iterator<ProcessRecord> kt = cpr.clients.iterator();
14329 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14330 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014331 if (client == app) {
14332 // Being our own client is not interesting.
14333 continue;
14334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014335 int myHiddenAdj = hiddenAdj;
14336 if (myHiddenAdj > client.hiddenAdj) {
14337 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
14338 myHiddenAdj = client.hiddenAdj;
14339 } else {
14340 myHiddenAdj = FOREGROUND_APP_ADJ;
14341 }
14342 }
14343 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014344 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014345 if (adj > clientAdj) {
14346 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014347 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014348 if (!client.hidden) {
14349 app.hidden = false;
14350 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014351 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014352 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14353 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014354 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014355 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014356 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014357 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14358 schedGroup = Process.THREAD_GROUP_DEFAULT;
14359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014360 }
14361 }
14362 // If the provider has external (non-framework) process
14363 // dependencies, ensure that its adjustment is at least
14364 // FOREGROUND_APP_ADJ.
14365 if (cpr.externals != 0) {
14366 if (adj > FOREGROUND_APP_ADJ) {
14367 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014368 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014369 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014370 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014371 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014372 }
14373 }
14374 }
14375 }
14376
14377 app.curRawAdj = adj;
14378
Joe Onorato8a9b2202010-02-26 18:56:32 -080014379 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014380 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14381 if (adj > app.maxAdj) {
14382 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014383 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014384 schedGroup = Process.THREAD_GROUP_DEFAULT;
14385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014386 }
14387
14388 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014389 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014391 return adj;
14392 }
14393
14394 /**
14395 * Ask a given process to GC right now.
14396 */
14397 final void performAppGcLocked(ProcessRecord app) {
14398 try {
14399 app.lastRequestedGc = SystemClock.uptimeMillis();
14400 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014401 if (app.reportLowMemory) {
14402 app.reportLowMemory = false;
14403 app.thread.scheduleLowMemory();
14404 } else {
14405 app.thread.processInBackground();
14406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014407 }
14408 } catch (Exception e) {
14409 // whatever.
14410 }
14411 }
14412
14413 /**
14414 * Returns true if things are idle enough to perform GCs.
14415 */
Josh Bartel7f208742010-02-25 11:01:44 -060014416 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014417 return mParallelBroadcasts.size() == 0
14418 && mOrderedBroadcasts.size() == 0
14419 && (mSleeping || (mResumedActivity != null &&
14420 mResumedActivity.idle));
14421 }
14422
14423 /**
14424 * Perform GCs on all processes that are waiting for it, but only
14425 * if things are idle.
14426 */
14427 final void performAppGcsLocked() {
14428 final int N = mProcessesToGc.size();
14429 if (N <= 0) {
14430 return;
14431 }
Josh Bartel7f208742010-02-25 11:01:44 -060014432 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014433 while (mProcessesToGc.size() > 0) {
14434 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014435 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014436 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14437 <= SystemClock.uptimeMillis()) {
14438 // To avoid spamming the system, we will GC processes one
14439 // at a time, waiting a few seconds between each.
14440 performAppGcLocked(proc);
14441 scheduleAppGcsLocked();
14442 return;
14443 } else {
14444 // It hasn't been long enough since we last GCed this
14445 // process... put it in the list to wait for its time.
14446 addProcessToGcListLocked(proc);
14447 break;
14448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014449 }
14450 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014451
14452 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014453 }
14454 }
14455
14456 /**
14457 * If all looks good, perform GCs on all processes waiting for them.
14458 */
14459 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014460 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014461 performAppGcsLocked();
14462 return;
14463 }
14464 // Still not idle, wait some more.
14465 scheduleAppGcsLocked();
14466 }
14467
14468 /**
14469 * Schedule the execution of all pending app GCs.
14470 */
14471 final void scheduleAppGcsLocked() {
14472 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014473
14474 if (mProcessesToGc.size() > 0) {
14475 // Schedule a GC for the time to the next process.
14476 ProcessRecord proc = mProcessesToGc.get(0);
14477 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14478
14479 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14480 long now = SystemClock.uptimeMillis();
14481 if (when < (now+GC_TIMEOUT)) {
14482 when = now + GC_TIMEOUT;
14483 }
14484 mHandler.sendMessageAtTime(msg, when);
14485 }
14486 }
14487
14488 /**
14489 * Add a process to the array of processes waiting to be GCed. Keeps the
14490 * list in sorted order by the last GC time. The process can't already be
14491 * on the list.
14492 */
14493 final void addProcessToGcListLocked(ProcessRecord proc) {
14494 boolean added = false;
14495 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14496 if (mProcessesToGc.get(i).lastRequestedGc <
14497 proc.lastRequestedGc) {
14498 added = true;
14499 mProcessesToGc.add(i+1, proc);
14500 break;
14501 }
14502 }
14503 if (!added) {
14504 mProcessesToGc.add(0, proc);
14505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014506 }
14507
14508 /**
14509 * Set up to ask a process to GC itself. This will either do it
14510 * immediately, or put it on the list of processes to gc the next
14511 * time things are idle.
14512 */
14513 final void scheduleAppGcLocked(ProcessRecord app) {
14514 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014515 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014516 return;
14517 }
14518 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014519 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014520 scheduleAppGcsLocked();
14521 }
14522 }
14523
14524 private final boolean updateOomAdjLocked(
14525 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14526 app.hiddenAdj = hiddenAdj;
14527
14528 if (app.thread == null) {
14529 return true;
14530 }
14531
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014532 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014533
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014534 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014535 if (app.curRawAdj != app.setRawAdj) {
14536 if (app.curRawAdj > FOREGROUND_APP_ADJ
14537 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14538 // If this app is transitioning from foreground to
14539 // non-foreground, have it do a gc.
14540 scheduleAppGcLocked(app);
14541 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14542 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14543 // Likewise do a gc when an app is moving in to the
14544 // background (such as a service stopping).
14545 scheduleAppGcLocked(app);
14546 }
14547 app.setRawAdj = app.curRawAdj;
14548 }
14549 if (adj != app.setAdj) {
14550 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014551 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014552 TAG, "Set app " + app.processName +
14553 " oom adj to " + adj);
14554 app.setAdj = adj;
14555 } else {
14556 return false;
14557 }
14558 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014559 if (app.setSchedGroup != app.curSchedGroup) {
14560 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014561 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014562 "Setting process group of " + app.processName
14563 + " to " + app.curSchedGroup);
14564 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014565 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014566 try {
14567 Process.setProcessGroup(app.pid, app.curSchedGroup);
14568 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014569 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014570 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014571 e.printStackTrace();
14572 } finally {
14573 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014574 }
14575 }
14576 if (false) {
14577 if (app.thread != null) {
14578 try {
14579 app.thread.setSchedulingGroup(app.curSchedGroup);
14580 } catch (RemoteException e) {
14581 }
14582 }
14583 }
14584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014585 }
14586
14587 return true;
14588 }
14589
14590 private final HistoryRecord resumedAppLocked() {
14591 HistoryRecord resumedActivity = mResumedActivity;
14592 if (resumedActivity == null || resumedActivity.app == null) {
14593 resumedActivity = mPausingActivity;
14594 if (resumedActivity == null || resumedActivity.app == null) {
14595 resumedActivity = topRunningActivityLocked(null);
14596 }
14597 }
14598 return resumedActivity;
14599 }
14600
14601 private final boolean updateOomAdjLocked(ProcessRecord app) {
14602 final HistoryRecord TOP_ACT = resumedAppLocked();
14603 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14604 int curAdj = app.curAdj;
14605 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14606 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14607
14608 mAdjSeq++;
14609
14610 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14611 if (res) {
14612 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14613 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14614 if (nowHidden != wasHidden) {
14615 // Changed to/from hidden state, so apps after it in the LRU
14616 // list may also be changed.
14617 updateOomAdjLocked();
14618 }
14619 }
14620 return res;
14621 }
14622
14623 private final boolean updateOomAdjLocked() {
14624 boolean didOomAdj = true;
14625 final HistoryRecord TOP_ACT = resumedAppLocked();
14626 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14627
14628 if (false) {
14629 RuntimeException e = new RuntimeException();
14630 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014631 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014632 }
14633
14634 mAdjSeq++;
14635
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014636 // Let's determine how many processes we have running vs.
14637 // how many slots we have for background processes; we may want
14638 // to put multiple processes in a slot of there are enough of
14639 // them.
14640 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14641 int factor = (mLruProcesses.size()-4)/numSlots;
14642 if (factor < 1) factor = 1;
14643 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014644 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014646 // First try updating the OOM adjustment for each of the
14647 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014648 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014649 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14650 while (i > 0) {
14651 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014652 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014653 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014654 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014655 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014656 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014657 step++;
14658 if (step >= factor) {
14659 step = 0;
14660 curHiddenAdj++;
14661 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014662 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014663 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070014664 if (!app.killedBackground) {
14665 numHidden++;
14666 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070014667 Slog.i(TAG, "No longer want " + app.processName
14668 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014669 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14670 app.processName, app.setAdj, "too many background");
14671 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070014672 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014673 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014674 }
14675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014676 } else {
14677 didOomAdj = false;
14678 }
14679 }
14680
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014681 // If we return false, we will fall back on killing processes to
14682 // have a fixed limit. Do this if a limit has been requested; else
14683 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014684 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14685 }
14686
14687 private final void trimApplications() {
14688 synchronized (this) {
14689 int i;
14690
14691 // First remove any unused application processes whose package
14692 // has been removed.
14693 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14694 final ProcessRecord app = mRemovedProcesses.get(i);
14695 if (app.activities.size() == 0
14696 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014697 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014698 TAG, "Exiting empty application process "
14699 + app.processName + " ("
14700 + (app.thread != null ? app.thread.asBinder() : null)
14701 + ")\n");
14702 if (app.pid > 0 && app.pid != MY_PID) {
14703 Process.killProcess(app.pid);
14704 } else {
14705 try {
14706 app.thread.scheduleExit();
14707 } catch (Exception e) {
14708 // Ignore exceptions.
14709 }
14710 }
14711 cleanUpApplicationRecordLocked(app, false, -1);
14712 mRemovedProcesses.remove(i);
14713
14714 if (app.persistent) {
14715 if (app.persistent) {
14716 addAppLocked(app.info);
14717 }
14718 }
14719 }
14720 }
14721
14722 // Now try updating the OOM adjustment for each of the
14723 // application processes based on their current state.
14724 // If the setOomAdj() API is not supported, then go with our
14725 // back-up plan...
14726 if (!updateOomAdjLocked()) {
14727
14728 // Count how many processes are running services.
14729 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014730 for (i=mLruProcesses.size()-1; i>=0; i--) {
14731 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014732
14733 if (app.persistent || app.services.size() != 0
14734 || app.curReceiver != null
14735 || app.persistentActivities > 0) {
14736 // Don't count processes holding services against our
14737 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014738 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014739 TAG, "Not trimming app " + app + " with services: "
14740 + app.services);
14741 numServiceProcs++;
14742 }
14743 }
14744
14745 int curMaxProcs = mProcessLimit;
14746 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14747 if (mAlwaysFinishActivities) {
14748 curMaxProcs = 1;
14749 }
14750 curMaxProcs += numServiceProcs;
14751
14752 // Quit as many processes as we can to get down to the desired
14753 // process count. First remove any processes that no longer
14754 // have activites running in them.
14755 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014756 i<mLruProcesses.size()
14757 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014758 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014759 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014760 // Quit an application only if it is not currently
14761 // running any activities.
14762 if (!app.persistent && app.activities.size() == 0
14763 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014764 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014765 TAG, "Exiting empty application process "
14766 + app.processName + " ("
14767 + (app.thread != null ? app.thread.asBinder() : null)
14768 + ")\n");
14769 if (app.pid > 0 && app.pid != MY_PID) {
14770 Process.killProcess(app.pid);
14771 } else {
14772 try {
14773 app.thread.scheduleExit();
14774 } catch (Exception e) {
14775 // Ignore exceptions.
14776 }
14777 }
14778 // todo: For now we assume the application is not buggy
14779 // or evil, and will quit as a result of our request.
14780 // Eventually we need to drive this off of the death
14781 // notification, and kill the process if it takes too long.
14782 cleanUpApplicationRecordLocked(app, false, i);
14783 i--;
14784 }
14785 }
14786
14787 // If we still have too many processes, now from the least
14788 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014789 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014790 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014791 " of " + curMaxProcs + " processes");
14792 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014793 i<mLruProcesses.size()
14794 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014795 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014796 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014797 // Quit the application only if we have a state saved for
14798 // all of its activities.
14799 boolean canQuit = !app.persistent && app.curReceiver == null
14800 && app.services.size() == 0
14801 && app.persistentActivities == 0;
14802 int NUMA = app.activities.size();
14803 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014804 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014805 TAG, "Looking to quit " + app.processName);
14806 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014807 HistoryRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014808 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014809 TAG, " " + r.intent.getComponent().flattenToShortString()
14810 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14811 canQuit = (r.haveState || !r.stateNotNeeded)
14812 && !r.visible && r.stopped;
14813 }
14814 if (canQuit) {
14815 // Finish all of the activities, and then the app itself.
14816 for (j=0; j<NUMA; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014817 HistoryRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014818 if (!r.finishing) {
14819 destroyActivityLocked(r, false);
14820 }
14821 r.resultTo = null;
14822 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014823 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014824 + app.processName + " ("
14825 + (app.thread != null ? app.thread.asBinder() : null)
14826 + ")\n");
14827 if (app.pid > 0 && app.pid != MY_PID) {
14828 Process.killProcess(app.pid);
14829 } else {
14830 try {
14831 app.thread.scheduleExit();
14832 } catch (Exception e) {
14833 // Ignore exceptions.
14834 }
14835 }
14836 // todo: For now we assume the application is not buggy
14837 // or evil, and will quit as a result of our request.
14838 // Eventually we need to drive this off of the death
14839 // notification, and kill the process if it takes too long.
14840 cleanUpApplicationRecordLocked(app, false, i);
14841 i--;
14842 //dump();
14843 }
14844 }
14845
14846 }
14847
14848 int curMaxActivities = MAX_ACTIVITIES;
14849 if (mAlwaysFinishActivities) {
14850 curMaxActivities = 1;
14851 }
14852
14853 // Finally, if there are too many activities now running, try to
14854 // finish as many as we can to get back down to the limit.
14855 for ( i=0;
14856 i<mLRUActivities.size()
14857 && mLRUActivities.size() > curMaxActivities;
14858 i++) {
14859 final HistoryRecord r
14860 = (HistoryRecord)mLRUActivities.get(i);
14861
14862 // We can finish this one if we have its icicle saved and
14863 // it is not persistent.
14864 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14865 && r.stopped && !r.persistent && !r.finishing) {
14866 final int origSize = mLRUActivities.size();
14867 destroyActivityLocked(r, true);
14868
14869 // This will remove it from the LRU list, so keep
14870 // our index at the same value. Note that this check to
14871 // see if the size changes is just paranoia -- if
14872 // something unexpected happens, we don't want to end up
14873 // in an infinite loop.
14874 if (origSize > mLRUActivities.size()) {
14875 i--;
14876 }
14877 }
14878 }
14879 }
14880 }
14881
14882 /** This method sends the specified signal to each of the persistent apps */
14883 public void signalPersistentProcesses(int sig) throws RemoteException {
14884 if (sig != Process.SIGNAL_USR1) {
14885 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14886 }
14887
14888 synchronized (this) {
14889 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14890 != PackageManager.PERMISSION_GRANTED) {
14891 throw new SecurityException("Requires permission "
14892 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14893 }
14894
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014895 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14896 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014897 if (r.thread != null && r.persistent) {
14898 Process.sendSignal(r.pid, sig);
14899 }
14900 }
14901 }
14902 }
14903
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014904 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014905 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014906
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014907 try {
14908 synchronized (this) {
14909 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14910 // its own permission.
14911 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14912 != PackageManager.PERMISSION_GRANTED) {
14913 throw new SecurityException("Requires permission "
14914 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014915 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014916
14917 if (start && fd == null) {
14918 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014919 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014920
14921 ProcessRecord proc = null;
14922 try {
14923 int pid = Integer.parseInt(process);
14924 synchronized (mPidsSelfLocked) {
14925 proc = mPidsSelfLocked.get(pid);
14926 }
14927 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014928 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014929
14930 if (proc == null) {
14931 HashMap<String, SparseArray<ProcessRecord>> all
14932 = mProcessNames.getMap();
14933 SparseArray<ProcessRecord> procs = all.get(process);
14934 if (procs != null && procs.size() > 0) {
14935 proc = procs.valueAt(0);
14936 }
14937 }
14938
14939 if (proc == null || proc.thread == null) {
14940 throw new IllegalArgumentException("Unknown process: " + process);
14941 }
14942
14943 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14944 if (isSecure) {
14945 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14946 throw new SecurityException("Process not debuggable: " + proc);
14947 }
14948 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014949
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014950 proc.thread.profilerControl(start, path, fd);
14951 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014952 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014953 }
14954 } catch (RemoteException e) {
14955 throw new IllegalStateException("Process disappeared");
14956 } finally {
14957 if (fd != null) {
14958 try {
14959 fd.close();
14960 } catch (IOException e) {
14961 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014962 }
14963 }
14964 }
14965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014966 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14967 public void monitor() {
14968 synchronized (this) { }
14969 }
14970}