blob: ec209eda3178a266a0789f36a154cf9a070e885f [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;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700100import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.os.SystemClock;
102import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.util.Config;
105import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800106import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800107import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import android.util.PrintWriterPrinter;
109import android.util.SparseArray;
110import android.view.Gravity;
111import android.view.LayoutInflater;
112import android.view.View;
113import android.view.WindowManager;
114import android.view.WindowManagerPolicy;
115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116import java.io.File;
117import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200119import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800120import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121import java.io.PrintWriter;
122import java.lang.IllegalStateException;
123import java.lang.ref.WeakReference;
124import java.util.ArrayList;
125import java.util.HashMap;
126import java.util.HashSet;
127import java.util.Iterator;
128import java.util.List;
129import java.util.Locale;
130import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700131import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700132import java.util.concurrent.atomic.AtomicBoolean;
133import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134
135public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
136 static final String TAG = "ActivityManager";
137 static final boolean DEBUG = false;
138 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
139 static final boolean DEBUG_SWITCH = localLOGV || false;
140 static final boolean DEBUG_TASKS = localLOGV || false;
141 static final boolean DEBUG_PAUSE = localLOGV || false;
142 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
143 static final boolean DEBUG_TRANSITION = localLOGV || false;
144 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700145 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 static final boolean DEBUG_SERVICE = localLOGV || false;
147 static final boolean DEBUG_VISBILITY = localLOGV || false;
148 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700149 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800150 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700152 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700153 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700154 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final boolean VALIDATE_TOKENS = false;
156 static final boolean SHOW_ACTIVITY_START_TIME = true;
157
158 // Control over CPU and battery monitoring.
159 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
160 static final boolean MONITOR_CPU_USAGE = true;
161 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
162 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
163 static final boolean MONITOR_THREAD_CPU_USAGE = false;
164
Dianne Hackborn1655be42009-05-08 14:29:01 -0700165 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700166 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 private static final String SYSTEM_SECURE = "ro.secure";
169
170 // This is the maximum number of application processes we would like
171 // to have running. Due to the asynchronous nature of things, we can
172 // temporarily go beyond this limit.
173 static final int MAX_PROCESSES = 2;
174
175 // Set to false to leave processes running indefinitely, relying on
176 // the kernel killing them as resources are required.
177 static final boolean ENFORCE_PROCESS_LIMIT = false;
178
179 // This is the maximum number of activities that we would like to have
180 // running at a given time.
181 static final int MAX_ACTIVITIES = 20;
182
183 // Maximum number of recent tasks that we can remember.
184 static final int MAX_RECENT_TASKS = 20;
185
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700186 // Amount of time after a call to stopAppSwitches() during which we will
187 // prevent further untrusted switches from happening.
188 static final long APP_SWITCH_DELAY_TIME = 5*1000;
189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 // How long until we reset a task when the user returns to it. Currently
191 // 30 minutes.
192 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
193
194 // Set to true to disable the icon that is shown while a new activity
195 // is being started.
196 static final boolean SHOW_APP_STARTING_ICON = true;
197
198 // How long we wait until giving up on the last activity to pause. This
199 // is short because it directly impacts the responsiveness of starting the
200 // next activity.
201 static final int PAUSE_TIMEOUT = 500;
202
203 /**
204 * How long we can hold the launch wake lock before giving up.
205 */
206 static final int LAUNCH_TIMEOUT = 10*1000;
207
208 // How long we wait for a launched process to attach to the activity manager
209 // before we decide it's never going to come up for real.
210 static final int PROC_START_TIMEOUT = 10*1000;
211
212 // How long we wait until giving up on the last activity telling us it
213 // is idle.
214 static final int IDLE_TIMEOUT = 10*1000;
215
216 // How long to wait after going idle before forcing apps to GC.
217 static final int GC_TIMEOUT = 5*1000;
218
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700219 // The minimum amount of time between successive GC requests for a process.
220 static final int GC_MIN_INTERVAL = 60*1000;
221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 // How long we wait until giving up on an activity telling us it has
223 // finished destroying itself.
224 static final int DESTROY_TIMEOUT = 10*1000;
225
226 // How long we allow a receiver to run before giving up on it.
227 static final int BROADCAST_TIMEOUT = 10*1000;
228
229 // How long we wait for a service to finish executing.
230 static final int SERVICE_TIMEOUT = 20*1000;
231
232 // How long a service needs to be running until restarting its process
233 // is no longer considered to be a relaunch of the service.
234 static final int SERVICE_RESTART_DURATION = 5*1000;
235
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700236 // How long a service needs to be running until it will start back at
237 // SERVICE_RESTART_DURATION after being killed.
238 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
239
240 // Multiplying factor to increase restart duration time by, for each time
241 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
242 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
243
244 // The minimum amount of time between restarting services that we allow.
245 // That is, when multiple services are restarting, we won't allow each
246 // to restart less than this amount of time from the last one.
247 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 // Maximum amount of time for there to be no activity on a service before
250 // we consider it non-essential and allow its process to go on the
251 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700252 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253
254 // How long we wait until we timeout on key dispatching.
255 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
256
257 // The minimum time we allow between crashes, for us to consider this
258 // application to be bad and stop and its services and reject broadcasts.
259 static final int MIN_CRASH_INTERVAL = 60*1000;
260
261 // How long we wait until we timeout on key dispatching during instrumentation.
262 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
263
264 // OOM adjustments for processes in various states:
265
266 // This is a process without anything currently running in it. Definitely
267 // the first to go! Value set in system/rootdir/init.rc on startup.
268 // This value is initalized in the constructor, careful when refering to
269 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800270 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271
272 // This is a process only hosting activities that are not visible,
273 // so it can be killed without any disruption. Value set in
274 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 static int HIDDEN_APP_MIN_ADJ;
277
The Android Open Source Project4df24232009-03-05 14:34:35 -0800278 // This is a process holding the home application -- we want to try
279 // avoiding killing it, even if it would normally be in the background,
280 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800281 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800282
Christopher Tate6fa95972009-06-05 18:43:55 -0700283 // This is a process currently hosting a backup operation. Killing it
284 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800285 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 // This is a process holding a secondary server -- killing it will not
288 // have much of an impact as far as the user is concerned. Value set in
289 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800290 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700292 // This is a process with a heavy-weight application. It is in the
293 // background, but we want to try to avoid killing it. Value set in
294 // system/rootdir/init.rc on startup.
295 static final int HEAVY_WEIGHT_APP_ADJ;
296
297 // This is a process only hosting components that are perceptible to the
298 // user, and we really want to avoid killing them, but they are not
299 // immediately visible. An example is background music playback. Value set in
300 // system/rootdir/init.rc on startup.
301 static final int PERCEPTIBLE_APP_ADJ;
302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 // This is a process only hosting activities that are visible to the
304 // user, so we'd prefer they don't disappear. Value set in
305 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307
308 // This is the process running the current foreground app. We'd really
309 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800310 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311
312 // This is a process running a core server, such as telephony. Definitely
313 // don't want to kill it, but doing so is not completely fatal.
314 static final int CORE_SERVER_ADJ = -12;
315
316 // The system process runs at the default adjustment.
317 static final int SYSTEM_ADJ = -16;
318
319 // Memory pages are 4K.
320 static final int PAGE_SIZE = 4*1024;
321
322 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800323 static final int EMPTY_APP_MEM;
324 static final int HIDDEN_APP_MEM;
325 static final int HOME_APP_MEM;
326 static final int BACKUP_APP_MEM;
327 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700328 static final int HEAVY_WEIGHT_APP_MEM;
329 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800330 static final int VISIBLE_APP_MEM;
331 static final int FOREGROUND_APP_MEM;
332
333 // The minimum number of hidden apps we want to be able to keep around,
334 // without empty apps being able to push them out of memory.
335 static final int MIN_HIDDEN_APPS = 2;
336
Dianne Hackborn8633e682010-04-22 16:03:41 -0700337 // The maximum number of hidden processes we will keep around before
338 // killing them; this is just a control to not let us go too crazy with
339 // keeping around processes on devices with large amounts of RAM.
340 static final int MAX_HIDDEN_APPS = 15;
341
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800342 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700343 // been idle for less than 15 seconds.
344 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800345
346 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700347 // been idle for less than 120 seconds.
348 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800349
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700350 static int getIntProp(String name, boolean allowZero) {
351 String str = SystemProperties.get(name);
352 if (str == null) {
353 throw new IllegalArgumentException("Property not defined: " + name);
354 }
355 int val = Integer.valueOf(str);
356 if (val == 0 && !allowZero) {
357 throw new IllegalArgumentException("Property must not be zero: " + name);
358 }
359 return val;
360 }
361
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800362 static {
363 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700364 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
365 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
366 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
367 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
368 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
369 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
370 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
371 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
372 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
373 // These days we use the last empty slot for hidden apps as well.
374 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
375 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
376 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
377 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
378 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
379 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
380 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
381 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
382 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
383 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385
Dan Egnor42471dd2010-01-07 17:25:22 -0800386 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387
388 static final String[] EMPTY_STRING_ARRAY = new String[0];
389
390 enum ActivityState {
391 INITIALIZING,
392 RESUMED,
393 PAUSING,
394 PAUSED,
395 STOPPING,
396 STOPPED,
397 FINISHING,
398 DESTROYING,
399 DESTROYED
400 }
401
402 /**
403 * The back history of all previous (and possibly still
404 * running) activities. It contains HistoryRecord objects.
405 */
406 final ArrayList mHistory = new ArrayList();
407
408 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700409 * Description of a request to start a new activity, which has been held
410 * due to app switches being disabled.
411 */
412 class PendingActivityLaunch {
413 HistoryRecord r;
414 HistoryRecord sourceRecord;
415 Uri[] grantedUriPermissions;
416 int grantedMode;
417 boolean onlyIfNeeded;
418 }
419
420 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
421 = new ArrayList<PendingActivityLaunch>();
422
423 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800424 * List of people waiting to find out about the next launched activity.
425 */
426 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
427 = new ArrayList<IActivityManager.WaitResult>();
428
429 /**
430 * List of people waiting to find out about the next visible activity.
431 */
432 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
433 = new ArrayList<IActivityManager.WaitResult>();
434
435 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 * List of all active broadcasts that are to be executed immediately
437 * (without waiting for another broadcast to finish). Currently this only
438 * contains broadcasts to registered receivers, to avoid spinning up
439 * a bunch of processes to execute IntentReceiver components.
440 */
441 final ArrayList<BroadcastRecord> mParallelBroadcasts
442 = new ArrayList<BroadcastRecord>();
443
444 /**
445 * List of all active broadcasts that are to be executed one at a time.
446 * The object at the top of the list is the currently activity broadcasts;
447 * those after it are waiting for the top to finish..
448 */
449 final ArrayList<BroadcastRecord> mOrderedBroadcasts
450 = new ArrayList<BroadcastRecord>();
451
452 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800453 * Historical data of past broadcasts, for debugging.
454 */
455 static final int MAX_BROADCAST_HISTORY = 100;
456 final BroadcastRecord[] mBroadcastHistory
457 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
458
459 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 * Set when we current have a BROADCAST_INTENT_MSG in flight.
461 */
462 boolean mBroadcastsScheduled = false;
463
464 /**
465 * Set to indicate whether to issue an onUserLeaving callback when a
466 * newly launched activity is being brought in front of us.
467 */
468 boolean mUserLeaving = false;
469
470 /**
471 * When we are in the process of pausing an activity, before starting the
472 * next one, this variable holds the activity that is currently being paused.
473 */
474 HistoryRecord mPausingActivity = null;
475
476 /**
477 * Current activity that is resumed, or null if there is none.
478 */
479 HistoryRecord mResumedActivity = null;
480
481 /**
482 * Activity we have told the window manager to have key focus.
483 */
484 HistoryRecord mFocusedActivity = null;
485
486 /**
487 * This is the last activity that we put into the paused state. This is
488 * used to determine if we need to do an activity transition while sleeping,
489 * when we normally hold the top activity paused.
490 */
491 HistoryRecord mLastPausedActivity = null;
492
493 /**
494 * List of activities that are waiting for a new activity
495 * to become visible before completing whatever operation they are
496 * supposed to do.
497 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700498 final ArrayList<HistoryRecord> mWaitingVisibleActivities
499 = new ArrayList<HistoryRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500
501 /**
502 * List of activities that are ready to be stopped, but waiting
503 * for the next activity to settle down before doing so. It contains
504 * HistoryRecord objects.
505 */
506 final ArrayList<HistoryRecord> mStoppingActivities
507 = new ArrayList<HistoryRecord>();
508
509 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700510 * Animations that for the current transition have requested not to
511 * be considered for the transition animation.
512 */
513 final ArrayList<HistoryRecord> mNoAnimActivities
514 = new ArrayList<HistoryRecord>();
515
516 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 * List of intents that were used to start the most recent tasks.
518 */
519 final ArrayList<TaskRecord> mRecentTasks
520 = new ArrayList<TaskRecord>();
521
522 /**
523 * List of activities that are ready to be finished, but waiting
524 * for the previous activity to settle down before doing so. It contains
525 * HistoryRecord objects.
526 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700527 final ArrayList<HistoryRecord> mFinishingActivities
528 = new ArrayList<HistoryRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529
530 /**
531 * All of the applications we currently have running organized by name.
532 * The keys are strings of the application package name (as
533 * returned by the package manager), and the keys are ApplicationRecord
534 * objects.
535 */
536 final ProcessMap<ProcessRecord> mProcessNames
537 = new ProcessMap<ProcessRecord>();
538
539 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700540 * The currently running heavy-weight process, if any.
541 */
542 ProcessRecord mHeavyWeightProcess = null;
543
544 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 * The last time that various processes have crashed.
546 */
547 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
548
549 /**
550 * Set of applications that we consider to be bad, and will reject
551 * incoming broadcasts from (which the user has no control over).
552 * Processes are added to this set when they have crashed twice within
553 * a minimum amount of time; they are removed from it when they are
554 * later restarted (hopefully due to some user action). The value is the
555 * time it was added to the list.
556 */
557 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
558
559 /**
560 * All of the processes we currently have running organized by pid.
561 * The keys are the pid running the application.
562 *
563 * <p>NOTE: This object is protected by its own lock, NOT the global
564 * activity manager lock!
565 */
566 final SparseArray<ProcessRecord> mPidsSelfLocked
567 = new SparseArray<ProcessRecord>();
568
569 /**
570 * All of the processes that have been forced to be foreground. The key
571 * is the pid of the caller who requested it (we hold a death
572 * link on it).
573 */
574 abstract class ForegroundToken implements IBinder.DeathRecipient {
575 int pid;
576 IBinder token;
577 }
578 final SparseArray<ForegroundToken> mForegroundProcesses
579 = new SparseArray<ForegroundToken>();
580
581 /**
582 * List of records for processes that someone had tried to start before the
583 * system was ready. We don't start them at that point, but ensure they
584 * are started by the time booting is complete.
585 */
586 final ArrayList<ProcessRecord> mProcessesOnHold
587 = new ArrayList<ProcessRecord>();
588
589 /**
590 * List of records for processes that we have started and are waiting
591 * for them to call back. This is really only needed when running in
592 * single processes mode, in which case we do not have a unique pid for
593 * each process.
594 */
595 final ArrayList<ProcessRecord> mStartingProcesses
596 = new ArrayList<ProcessRecord>();
597
598 /**
599 * List of persistent applications that are in the process
600 * of being started.
601 */
602 final ArrayList<ProcessRecord> mPersistentStartingProcesses
603 = new ArrayList<ProcessRecord>();
604
605 /**
606 * Processes that are being forcibly torn down.
607 */
608 final ArrayList<ProcessRecord> mRemovedProcesses
609 = new ArrayList<ProcessRecord>();
610
611 /**
612 * List of running applications, sorted by recent usage.
613 * The first entry in the list is the least recently used.
614 * It contains ApplicationRecord objects. This list does NOT include
615 * any persistent application records (since we never want to exit them).
616 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800617 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 = new ArrayList<ProcessRecord>();
619
620 /**
621 * List of processes that should gc as soon as things are idle.
622 */
623 final ArrayList<ProcessRecord> mProcessesToGc
624 = new ArrayList<ProcessRecord>();
625
626 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800627 * This is the process holding what we currently consider to be
628 * the "home" activity.
629 */
630 private ProcessRecord mHomeProcess;
631
632 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 * List of running activities, sorted by recent usage.
634 * The first entry in the list is the least recently used.
635 * It contains HistoryRecord objects.
636 */
637 private final ArrayList mLRUActivities = new ArrayList();
638
639 /**
640 * Set of PendingResultRecord objects that are currently active.
641 */
642 final HashSet mPendingResultRecords = new HashSet();
643
644 /**
645 * Set of IntentSenderRecord objects that are currently active.
646 */
647 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
648 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
649
650 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700651 * Fingerprints (String.hashCode()) of stack traces that we've
652 * already logged DropBox entries for. Guarded by itself. If
653 * something (rogue user app) forces this over
654 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
655 */
656 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
657 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
658
659 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 * Intent broadcast that we have tried to start, but are
661 * waiting for its application's process to be created. We only
662 * need one (instead of a list) because we always process broadcasts
663 * one at a time, so no others can be started while waiting for this
664 * one.
665 */
666 BroadcastRecord mPendingBroadcast = null;
667
668 /**
669 * Keeps track of all IIntentReceivers that have been registered for
670 * broadcasts. Hash keys are the receiver IBinder, hash value is
671 * a ReceiverList.
672 */
673 final HashMap mRegisteredReceivers = new HashMap();
674
675 /**
676 * Resolver for broadcast intents to registered receivers.
677 * Holds BroadcastFilter (subclass of IntentFilter).
678 */
679 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
680 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
681 @Override
682 protected boolean allowFilterResult(
683 BroadcastFilter filter, List<BroadcastFilter> dest) {
684 IBinder target = filter.receiverList.receiver.asBinder();
685 for (int i=dest.size()-1; i>=0; i--) {
686 if (dest.get(i).receiverList.receiver.asBinder() == target) {
687 return false;
688 }
689 }
690 return true;
691 }
692 };
693
694 /**
695 * State of all active sticky broadcasts. Keys are the action of the
696 * sticky Intent, values are an ArrayList of all broadcasted intents with
697 * that action (which should usually be one).
698 */
699 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
700 new HashMap<String, ArrayList<Intent>>();
701
702 /**
703 * All currently running services.
704 */
705 final HashMap<ComponentName, ServiceRecord> mServices =
706 new HashMap<ComponentName, ServiceRecord>();
707
708 /**
709 * All currently running services indexed by the Intent used to start them.
710 */
711 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
712 new HashMap<Intent.FilterComparison, ServiceRecord>();
713
714 /**
715 * All currently bound service connections. Keys are the IBinder of
716 * the client's IServiceConnection.
717 */
718 final HashMap<IBinder, ConnectionRecord> mServiceConnections
719 = new HashMap<IBinder, ConnectionRecord>();
720
721 /**
722 * List of services that we have been asked to start,
723 * but haven't yet been able to. It is used to hold start requests
724 * while waiting for their corresponding application thread to get
725 * going.
726 */
727 final ArrayList<ServiceRecord> mPendingServices
728 = new ArrayList<ServiceRecord>();
729
730 /**
731 * List of services that are scheduled to restart following a crash.
732 */
733 final ArrayList<ServiceRecord> mRestartingServices
734 = new ArrayList<ServiceRecord>();
735
736 /**
737 * List of services that are in the process of being stopped.
738 */
739 final ArrayList<ServiceRecord> mStoppingServices
740 = new ArrayList<ServiceRecord>();
741
742 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700743 * Backup/restore process management
744 */
745 String mBackupAppName = null;
746 BackupRecord mBackupTarget = null;
747
748 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 * List of PendingThumbnailsRecord objects of clients who are still
750 * waiting to receive all of the thumbnails for a task.
751 */
752 final ArrayList mPendingThumbnails = new ArrayList();
753
754 /**
755 * List of HistoryRecord objects that have been finished and must
756 * still report back to a pending thumbnail receiver.
757 */
758 final ArrayList mCancelledThumbnails = new ArrayList();
759
760 /**
761 * All of the currently running global content providers. Keys are a
762 * string containing the provider name and values are a
763 * ContentProviderRecord object containing the data about it. Note
764 * that a single provider may be published under multiple names, so
765 * there may be multiple entries here for a single one in mProvidersByClass.
766 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700767 final HashMap<String, ContentProviderRecord> mProvidersByName
768 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769
770 /**
771 * All of the currently running global content providers. Keys are a
772 * string containing the provider's implementation class and values are a
773 * ContentProviderRecord object containing the data about it.
774 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700775 final HashMap<String, ContentProviderRecord> mProvidersByClass
776 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777
778 /**
779 * List of content providers who have clients waiting for them. The
780 * application is currently being launched and the provider will be
781 * removed from this list once it is published.
782 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700783 final ArrayList<ContentProviderRecord> mLaunchingProviders
784 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785
786 /**
787 * Global set of specific Uri permissions that have been granted.
788 */
789 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
790 = new SparseArray<HashMap<Uri, UriPermission>>();
791
792 /**
793 * Thread-local storage used to carry caller permissions over through
794 * indirect content-provider access.
795 * @see #ActivityManagerService.openContentUri()
796 */
797 private class Identity {
798 public int pid;
799 public int uid;
800
801 Identity(int _pid, int _uid) {
802 pid = _pid;
803 uid = _uid;
804 }
805 }
806 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
807
808 /**
809 * All information we have collected about the runtime performance of
810 * any user id that can impact battery performance.
811 */
812 final BatteryStatsService mBatteryStatsService;
813
814 /**
815 * information about component usage
816 */
817 final UsageStatsService mUsageStatsService;
818
819 /**
820 * Current configuration information. HistoryRecord objects are given
821 * a reference to this object to indicate which configuration they are
822 * currently running in, so this object must be kept immutable.
823 */
824 Configuration mConfiguration = new Configuration();
825
826 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800827 * Current sequencing integer of the configuration, for skipping old
828 * configurations.
829 */
830 int mConfigurationSeq = 0;
831
832 /**
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700833 * Set when we know we are going to be calling updateConfiguration()
834 * soon, so want to skip intermediate config checks.
835 */
836 boolean mConfigWillChange;
837
838 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700839 * Hardware-reported OpenGLES version.
840 */
841 final int GL_ES_VERSION;
842
843 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 * List of initialization arguments to pass to all processes when binding applications to them.
845 * For example, references to the commonly used services.
846 */
847 HashMap<String, IBinder> mAppBindArgs;
848
849 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700850 * Temporary to avoid allocations. Protected by main lock.
851 */
852 final StringBuilder mStringBuilder = new StringBuilder(256);
853
854 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 * Used to control how we initialize the service.
856 */
857 boolean mStartRunning = false;
858 ComponentName mTopComponent;
859 String mTopAction;
860 String mTopData;
861 boolean mSystemReady = false;
862 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700863 boolean mWaitingUpdate = false;
864 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865
866 Context mContext;
867
868 int mFactoryTest;
869
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700870 boolean mCheckedForSetup;
871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700873 * The time at which we will allow normal application switches again,
874 * after a call to {@link #stopAppSwitches()}.
875 */
876 long mAppSwitchesAllowedTime;
877
878 /**
879 * This is set to true after the first switch after mAppSwitchesAllowedTime
880 * is set; any switches after that will clear the time.
881 */
882 boolean mDidAppSwitch;
883
884 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800885 * Set while we are wanting to sleep, to prevent any
886 * activities from being started/resumed.
887 */
888 boolean mSleeping = false;
889
890 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700891 * Set if we are shutting down the system, similar to sleeping.
892 */
893 boolean mShuttingDown = false;
894
895 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800896 * Set when the system is going to sleep, until we have
897 * successfully paused the current activity and released our wake lock.
898 * At that point the system is allowed to actually sleep.
899 */
900 PowerManager.WakeLock mGoingToSleep;
901
902 /**
903 * We don't want to allow the device to go to sleep while in the process
904 * of launching an activity. This is primarily to allow alarm intent
905 * receivers to launch an activity and get that to run before the device
906 * goes back to sleep.
907 */
908 PowerManager.WakeLock mLaunchingActivity;
909
910 /**
911 * Task identifier that activities are currently being started
912 * in. Incremented each time a new task is created.
913 * todo: Replace this with a TokenSpace class that generates non-repeating
914 * integers that won't wrap.
915 */
916 int mCurTask = 1;
917
918 /**
919 * Current sequence id for oom_adj computation traversal.
920 */
921 int mAdjSeq = 0;
922
923 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700924 * Current sequence id for process LRU updating.
925 */
926 int mLruSeq = 0;
927
928 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
930 * is set, indicating the user wants processes started in such a way
931 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
932 * running in each process (thus no pre-initialized process, etc).
933 */
934 boolean mSimpleProcessManagement = false;
935
936 /**
937 * System monitoring: number of processes that died since the last
938 * N procs were started.
939 */
940 int[] mProcDeaths = new int[20];
941
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700942 /**
943 * This is set if we had to do a delayed dexopt of an app before launching
944 * it, to increasing the ANR timeouts in that case.
945 */
946 boolean mDidDexOpt;
947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 String mDebugApp = null;
949 boolean mWaitForDebugger = false;
950 boolean mDebugTransient = false;
951 String mOrigDebugApp = null;
952 boolean mOrigWaitForDebugger = false;
953 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700954 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700956 final RemoteCallbackList<IActivityWatcher> mWatchers
957 = new RemoteCallbackList<IActivityWatcher>();
958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 /**
960 * Callback of last caller to {@link #requestPss}.
961 */
962 Runnable mRequestPssCallback;
963
964 /**
965 * Remaining processes for which we are waiting results from the last
966 * call to {@link #requestPss}.
967 */
968 final ArrayList<ProcessRecord> mRequestPssList
969 = new ArrayList<ProcessRecord>();
970
971 /**
972 * Runtime statistics collection thread. This object's lock is used to
973 * protect all related state.
974 */
975 final Thread mProcessStatsThread;
976
977 /**
978 * Used to collect process stats when showing not responding dialog.
979 * Protected by mProcessStatsThread.
980 */
981 final ProcessStats mProcessStats = new ProcessStats(
982 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700983 final AtomicLong mLastCpuTime = new AtomicLong(0);
984 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 long mLastWriteTime = 0;
987
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700988 long mInitialStartTime = 0;
989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 /**
991 * Set to true after the system has finished booting.
992 */
993 boolean mBooted = false;
994
995 int mProcessLimit = 0;
996
997 WindowManagerService mWindowManager;
998
999 static ActivityManagerService mSelf;
1000 static ActivityThread mSystemThread;
1001
1002 private final class AppDeathRecipient implements IBinder.DeathRecipient {
1003 final ProcessRecord mApp;
1004 final int mPid;
1005 final IApplicationThread mAppThread;
1006
1007 AppDeathRecipient(ProcessRecord app, int pid,
1008 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001009 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 TAG, "New death recipient " + this
1011 + " for thread " + thread.asBinder());
1012 mApp = app;
1013 mPid = pid;
1014 mAppThread = thread;
1015 }
1016
1017 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001018 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 TAG, "Death received in " + this
1020 + " for thread " + mAppThread.asBinder());
1021 removeRequestedPss(mApp);
1022 synchronized(ActivityManagerService.this) {
1023 appDiedLocked(mApp, mPid, mAppThread);
1024 }
1025 }
1026 }
1027
1028 static final int SHOW_ERROR_MSG = 1;
1029 static final int SHOW_NOT_RESPONDING_MSG = 2;
1030 static final int SHOW_FACTORY_ERROR_MSG = 3;
1031 static final int UPDATE_CONFIGURATION_MSG = 4;
1032 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
1033 static final int WAIT_FOR_DEBUGGER_MSG = 6;
1034 static final int BROADCAST_INTENT_MSG = 7;
1035 static final int BROADCAST_TIMEOUT_MSG = 8;
1036 static final int PAUSE_TIMEOUT_MSG = 9;
1037 static final int IDLE_TIMEOUT_MSG = 10;
1038 static final int IDLE_NOW_MSG = 11;
1039 static final int SERVICE_TIMEOUT_MSG = 12;
1040 static final int UPDATE_TIME_ZONE = 13;
1041 static final int SHOW_UID_ERROR_MSG = 14;
1042 static final int IM_FEELING_LUCKY_MSG = 15;
1043 static final int LAUNCH_TIMEOUT_MSG = 16;
1044 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 static final int RESUME_TOP_ACTIVITY_MSG = 19;
1046 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001047 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001048 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001049 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001050 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
1051 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001052 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053
1054 AlertDialog mUidAlert;
1055
1056 final Handler mHandler = new Handler() {
1057 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001058 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059 //}
1060
1061 public void handleMessage(Message msg) {
1062 switch (msg.what) {
1063 case SHOW_ERROR_MSG: {
1064 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 synchronized (ActivityManagerService.this) {
1066 ProcessRecord proc = (ProcessRecord)data.get("app");
1067 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001068 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 return;
1070 }
1071 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001072 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001073 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 d.show();
1075 proc.crashDialog = d;
1076 } else {
1077 // The device is asleep, so just pretend that the user
1078 // saw a crash dialog and hit "force quit".
1079 res.set(0);
1080 }
1081 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001082
1083 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 } break;
1085 case SHOW_NOT_RESPONDING_MSG: {
1086 synchronized (ActivityManagerService.this) {
1087 HashMap data = (HashMap) msg.obj;
1088 ProcessRecord proc = (ProcessRecord)data.get("app");
1089 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001090 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 return;
1092 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001093
1094 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1095 null, null, 0, null, null, null,
1096 false, false, MY_PID, Process.SYSTEM_UID);
1097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1099 mContext, proc, (HistoryRecord)data.get("activity"));
1100 d.show();
1101 proc.anrDialog = d;
1102 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001103
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001104 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001106 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1107 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1108 synchronized (ActivityManagerService.this) {
1109 ProcessRecord proc = (ProcessRecord) data.get("app");
1110 if (proc == null) {
1111 Slog.e(TAG, "App not found when showing strict mode dialog.");
1112 break;
1113 }
1114 if (proc.crashDialog != null) {
1115 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1116 return;
1117 }
1118 AppErrorResult res = (AppErrorResult) data.get("result");
1119 if (!mSleeping && !mShuttingDown) {
1120 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1121 d.show();
1122 proc.crashDialog = d;
1123 } else {
1124 // The device is asleep, so just pretend that the user
1125 // saw a crash dialog and hit "force quit".
1126 res.set(0);
1127 }
1128 }
1129 ensureBootCompleted();
1130 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 case SHOW_FACTORY_ERROR_MSG: {
1132 Dialog d = new FactoryErrorDialog(
1133 mContext, msg.getData().getCharSequence("msg"));
1134 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001135 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 } break;
1137 case UPDATE_CONFIGURATION_MSG: {
1138 final ContentResolver resolver = mContext.getContentResolver();
1139 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1140 } break;
1141 case GC_BACKGROUND_PROCESSES_MSG: {
1142 synchronized (ActivityManagerService.this) {
1143 performAppGcsIfAppropriateLocked();
1144 }
1145 } break;
1146 case WAIT_FOR_DEBUGGER_MSG: {
1147 synchronized (ActivityManagerService.this) {
1148 ProcessRecord app = (ProcessRecord)msg.obj;
1149 if (msg.arg1 != 0) {
1150 if (!app.waitedForDebugger) {
1151 Dialog d = new AppWaitingForDebuggerDialog(
1152 ActivityManagerService.this,
1153 mContext, app);
1154 app.waitDialog = d;
1155 app.waitedForDebugger = true;
1156 d.show();
1157 }
1158 } else {
1159 if (app.waitDialog != null) {
1160 app.waitDialog.dismiss();
1161 app.waitDialog = null;
1162 }
1163 }
1164 }
1165 } break;
1166 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001167 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168 TAG, "Received BROADCAST_INTENT_MSG");
1169 processNextBroadcast(true);
1170 } break;
1171 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001172 if (mDidDexOpt) {
1173 mDidDexOpt = false;
1174 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1175 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1176 return;
1177 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001178 // Only process broadcast timeouts if the system is ready. That way
1179 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1180 // to do heavy lifting for system up
1181 if (mSystemReady) {
1182 broadcastTimeout();
1183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 } break;
1185 case PAUSE_TIMEOUT_MSG: {
1186 IBinder token = (IBinder)msg.obj;
1187 // We don't at this point know if the activity is fullscreen,
1188 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001189 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 activityPaused(token, null, true);
1191 } break;
1192 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001193 if (mDidDexOpt) {
1194 mDidDexOpt = false;
1195 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1196 nmsg.obj = msg.obj;
1197 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1198 return;
1199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 // We don't at this point know if the activity is fullscreen,
1201 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001202 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001203 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001204 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 } break;
1206 case DESTROY_TIMEOUT_MSG: {
1207 IBinder token = (IBinder)msg.obj;
1208 // We don't at this point know if the activity is fullscreen,
1209 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001210 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 activityDestroyed(token);
1212 } break;
1213 case IDLE_NOW_MSG: {
1214 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001215 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216 } break;
1217 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001218 if (mDidDexOpt) {
1219 mDidDexOpt = false;
1220 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1221 nmsg.obj = msg.obj;
1222 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1223 return;
1224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 serviceTimeout((ProcessRecord)msg.obj);
1226 } break;
1227 case UPDATE_TIME_ZONE: {
1228 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001229 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1230 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 if (r.thread != null) {
1232 try {
1233 r.thread.updateTimeZone();
1234 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001235 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 }
1237 }
1238 }
1239 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001240 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241 case SHOW_UID_ERROR_MSG: {
1242 // XXX This is a temporary dialog, no need to localize.
1243 AlertDialog d = new BaseErrorDialog(mContext);
1244 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1245 d.setCancelable(false);
1246 d.setTitle("System UIDs Inconsistent");
1247 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1248 d.setButton("I'm Feeling Lucky",
1249 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1250 mUidAlert = d;
1251 d.show();
1252 } break;
1253 case IM_FEELING_LUCKY_MSG: {
1254 if (mUidAlert != null) {
1255 mUidAlert.dismiss();
1256 mUidAlert = null;
1257 }
1258 } break;
1259 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001260 if (mDidDexOpt) {
1261 mDidDexOpt = false;
1262 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1263 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1264 return;
1265 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 synchronized (ActivityManagerService.this) {
1267 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001268 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001269 mLaunchingActivity.release();
1270 }
1271 }
1272 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 case RESUME_TOP_ACTIVITY_MSG: {
1274 synchronized (ActivityManagerService.this) {
1275 resumeTopActivityLocked(null);
1276 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001277 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001279 if (mDidDexOpt) {
1280 mDidDexOpt = false;
1281 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1282 nmsg.obj = msg.obj;
1283 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1284 return;
1285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 ProcessRecord app = (ProcessRecord)msg.obj;
1287 synchronized (ActivityManagerService.this) {
1288 processStartTimedOutLocked(app);
1289 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001290 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001291 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1292 synchronized (ActivityManagerService.this) {
1293 doPendingActivityLaunchesLocked(true);
1294 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001295 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001296 case KILL_APPLICATION_MSG: {
1297 synchronized (ActivityManagerService.this) {
1298 int uid = msg.arg1;
1299 boolean restart = (msg.arg2 == 1);
1300 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001301 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001302 }
1303 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001304 case FINALIZE_PENDING_INTENT_MSG: {
1305 ((PendingIntentRecord)msg.obj).completeFinalize();
1306 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001307 case POST_HEAVY_NOTIFICATION_MSG: {
1308 INotificationManager inm = NotificationManager.getService();
1309 if (inm == null) {
1310 return;
1311 }
1312
1313 HistoryRecord root = (HistoryRecord)msg.obj;
1314 ProcessRecord process = root.app;
1315 if (process == null) {
1316 return;
1317 }
1318
1319 try {
1320 Context context = mContext.createPackageContext(process.info.packageName, 0);
1321 String text = mContext.getString(R.string.heavy_weight_notification,
1322 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1323 Notification notification = new Notification();
1324 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1325 notification.when = 0;
1326 notification.flags = Notification.FLAG_ONGOING_EVENT;
1327 notification.tickerText = text;
1328 notification.defaults = 0; // please be quiet
1329 notification.sound = null;
1330 notification.vibrate = null;
1331 notification.setLatestEventInfo(context, text,
1332 mContext.getText(R.string.heavy_weight_notification_detail),
1333 PendingIntent.getActivity(mContext, 0, root.intent,
1334 PendingIntent.FLAG_CANCEL_CURRENT));
1335
1336 try {
1337 int[] outId = new int[1];
1338 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1339 notification, outId);
1340 } catch (RuntimeException e) {
1341 Slog.w(ActivityManagerService.TAG,
1342 "Error showing notification for heavy-weight app", e);
1343 } catch (RemoteException e) {
1344 }
1345 } catch (NameNotFoundException e) {
1346 Log.w(TAG, "Unable to create context for heavy notification", e);
1347 }
1348 } break;
1349 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1350 INotificationManager inm = NotificationManager.getService();
1351 if (inm == null) {
1352 return;
1353 }
1354 try {
1355 inm.cancelNotification("android",
1356 R.string.heavy_weight_notification);
1357 } catch (RuntimeException e) {
1358 Slog.w(ActivityManagerService.TAG,
1359 "Error canceling notification for service", e);
1360 } catch (RemoteException e) {
1361 }
1362 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 }
1364 }
1365 };
1366
1367 public static void setSystemProcess() {
1368 try {
1369 ActivityManagerService m = mSelf;
1370
1371 ServiceManager.addService("activity", m);
1372 ServiceManager.addService("meminfo", new MemBinder(m));
1373 if (MONITOR_CPU_USAGE) {
1374 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001376 ServiceManager.addService("permission", new PermissionController(m));
1377
1378 ApplicationInfo info =
1379 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001380 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001381 mSystemThread.installSystemApplicationInfo(info);
1382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 synchronized (mSelf) {
1384 ProcessRecord app = mSelf.newProcessRecordLocked(
1385 mSystemThread.getApplicationThread(), info,
1386 info.processName);
1387 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001388 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 app.maxAdj = SYSTEM_ADJ;
1390 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1391 synchronized (mSelf.mPidsSelfLocked) {
1392 mSelf.mPidsSelfLocked.put(app.pid, app);
1393 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001394 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 }
1396 } catch (PackageManager.NameNotFoundException e) {
1397 throw new RuntimeException(
1398 "Unable to find android system package", e);
1399 }
1400 }
1401
1402 public void setWindowManager(WindowManagerService wm) {
1403 mWindowManager = wm;
1404 }
1405
1406 public static final Context main(int factoryTest) {
1407 AThread thr = new AThread();
1408 thr.start();
1409
1410 synchronized (thr) {
1411 while (thr.mService == null) {
1412 try {
1413 thr.wait();
1414 } catch (InterruptedException e) {
1415 }
1416 }
1417 }
1418
1419 ActivityManagerService m = thr.mService;
1420 mSelf = m;
1421 ActivityThread at = ActivityThread.systemMain();
1422 mSystemThread = at;
1423 Context context = at.getSystemContext();
1424 m.mContext = context;
1425 m.mFactoryTest = factoryTest;
1426 PowerManager pm =
1427 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1428 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1429 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1430 m.mLaunchingActivity.setReferenceCounted(false);
1431
1432 m.mBatteryStatsService.publish(context);
1433 m.mUsageStatsService.publish(context);
1434
1435 synchronized (thr) {
1436 thr.mReady = true;
1437 thr.notifyAll();
1438 }
1439
1440 m.startRunning(null, null, null, null);
1441
1442 return context;
1443 }
1444
1445 public static ActivityManagerService self() {
1446 return mSelf;
1447 }
1448
1449 static class AThread extends Thread {
1450 ActivityManagerService mService;
1451 boolean mReady = false;
1452
1453 public AThread() {
1454 super("ActivityManager");
1455 }
1456
1457 public void run() {
1458 Looper.prepare();
1459
1460 android.os.Process.setThreadPriority(
1461 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1462
1463 ActivityManagerService m = new ActivityManagerService();
1464
1465 synchronized (this) {
1466 mService = m;
1467 notifyAll();
1468 }
1469
1470 synchronized (this) {
1471 while (!mReady) {
1472 try {
1473 wait();
1474 } catch (InterruptedException e) {
1475 }
1476 }
1477 }
1478
1479 Looper.loop();
1480 }
1481 }
1482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 static class MemBinder extends Binder {
1484 ActivityManagerService mActivityManagerService;
1485 MemBinder(ActivityManagerService activityManagerService) {
1486 mActivityManagerService = activityManagerService;
1487 }
1488
1489 @Override
1490 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1491 ActivityManagerService service = mActivityManagerService;
1492 ArrayList<ProcessRecord> procs;
1493 synchronized (mActivityManagerService) {
1494 if (args != null && args.length > 0
1495 && args[0].charAt(0) != '-') {
1496 procs = new ArrayList<ProcessRecord>();
1497 int pid = -1;
1498 try {
1499 pid = Integer.parseInt(args[0]);
1500 } catch (NumberFormatException e) {
1501
1502 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001503 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1504 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 if (proc.pid == pid) {
1506 procs.add(proc);
1507 } else if (proc.processName.equals(args[0])) {
1508 procs.add(proc);
1509 }
1510 }
1511 if (procs.size() <= 0) {
1512 pw.println("No process found for: " + args[0]);
1513 return;
1514 }
1515 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001516 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 }
1518 }
1519 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1520 }
1521 }
1522
1523 static class CpuBinder extends Binder {
1524 ActivityManagerService mActivityManagerService;
1525 CpuBinder(ActivityManagerService activityManagerService) {
1526 mActivityManagerService = activityManagerService;
1527 }
1528
1529 @Override
1530 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1531 synchronized (mActivityManagerService.mProcessStatsThread) {
1532 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1533 }
1534 }
1535 }
1536
1537 private ActivityManagerService() {
1538 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1539 if (v != null && Integer.getInteger(v) != 0) {
1540 mSimpleProcessManagement = true;
1541 }
1542 v = System.getenv("ANDROID_DEBUG_APP");
1543 if (v != null) {
1544 mSimpleProcessManagement = true;
1545 }
1546
Joe Onorato8a9b2202010-02-26 18:56:32 -08001547 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 File dataDir = Environment.getDataDirectory();
1550 File systemDir = new File(dataDir, "system");
1551 systemDir.mkdirs();
1552 mBatteryStatsService = new BatteryStatsService(new File(
1553 systemDir, "batterystats.bin").toString());
1554 mBatteryStatsService.getActiveStatistics().readLocked();
1555 mBatteryStatsService.getActiveStatistics().writeLocked();
1556
1557 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001558 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559
Jack Palevichb90d28c2009-07-22 15:35:24 -07001560 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1561 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1562
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001563 mConfiguration.setToDefaults();
1564 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 mProcessStats.init();
1566
1567 // Add ourself to the Watchdog monitors.
1568 Watchdog.getInstance().addMonitor(this);
1569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 mProcessStatsThread = new Thread("ProcessStats") {
1571 public void run() {
1572 while (true) {
1573 try {
1574 try {
1575 synchronized(this) {
1576 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001577 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001579 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 // + ", write delay=" + nextWriteDelay);
1581 if (nextWriteDelay < nextCpuDelay) {
1582 nextCpuDelay = nextWriteDelay;
1583 }
1584 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001585 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 this.wait(nextCpuDelay);
1587 }
1588 }
1589 } catch (InterruptedException e) {
1590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 updateCpuStatsNow();
1592 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001593 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 }
1595 }
1596 }
1597 };
1598 mProcessStatsThread.start();
1599 }
1600
1601 @Override
1602 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1603 throws RemoteException {
1604 try {
1605 return super.onTransact(code, data, reply, flags);
1606 } catch (RuntimeException e) {
1607 // The activity manager only throws security exceptions, so let's
1608 // log all others.
1609 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001610 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 }
1612 throw e;
1613 }
1614 }
1615
1616 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001617 final long now = SystemClock.uptimeMillis();
1618 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1619 return;
1620 }
1621 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1622 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 mProcessStatsThread.notify();
1624 }
1625 }
1626 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 void updateCpuStatsNow() {
1629 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001630 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 final long now = SystemClock.uptimeMillis();
1632 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001635 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1636 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 haveNewCpuStats = true;
1638 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001639 //Slog.i(TAG, mProcessStats.printCurrentState());
1640 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 // + mProcessStats.getTotalCpuPercent() + "%");
1642
Joe Onorato8a9b2202010-02-26 18:56:32 -08001643 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 if ("true".equals(SystemProperties.get("events.cpu"))) {
1645 int user = mProcessStats.getLastUserTime();
1646 int system = mProcessStats.getLastSystemTime();
1647 int iowait = mProcessStats.getLastIoWaitTime();
1648 int irq = mProcessStats.getLastIrqTime();
1649 int softIrq = mProcessStats.getLastSoftIrqTime();
1650 int idle = mProcessStats.getLastIdleTime();
1651
1652 int total = user + system + iowait + irq + softIrq + idle;
1653 if (total == 0) total = 1;
1654
Doug Zongker2bec3d42009-12-04 12:52:44 -08001655 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001656 ((user+system+iowait+irq+softIrq) * 100) / total,
1657 (user * 100) / total,
1658 (system * 100) / total,
1659 (iowait * 100) / total,
1660 (irq * 100) / total,
1661 (softIrq * 100) / total);
1662 }
1663 }
1664
Amith Yamasanie43530a2009-08-21 13:11:37 -07001665 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001666 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001667 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 synchronized(mPidsSelfLocked) {
1669 if (haveNewCpuStats) {
1670 if (mBatteryStatsService.isOnBattery()) {
1671 final int N = mProcessStats.countWorkingStats();
1672 for (int i=0; i<N; i++) {
1673 ProcessStats.Stats st
1674 = mProcessStats.getWorkingStats(i);
1675 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1676 if (pr != null) {
1677 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1678 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001679 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001680 } else {
1681 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001682 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001683 if (ps != null) {
1684 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001685 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 }
1688 }
1689 }
1690 }
1691 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1694 mLastWriteTime = now;
1695 mBatteryStatsService.getActiveStatistics().writeLocked();
1696 }
1697 }
1698 }
1699 }
1700
1701 /**
1702 * Initialize the application bind args. These are passed to each
1703 * process when the bindApplication() IPC is sent to the process. They're
1704 * lazily setup to make sure the services are running when they're asked for.
1705 */
1706 private HashMap<String, IBinder> getCommonServicesLocked() {
1707 if (mAppBindArgs == null) {
1708 mAppBindArgs = new HashMap<String, IBinder>();
1709
1710 // Setup the application init args
1711 mAppBindArgs.put("package", ServiceManager.getService("package"));
1712 mAppBindArgs.put("window", ServiceManager.getService("window"));
1713 mAppBindArgs.put(Context.ALARM_SERVICE,
1714 ServiceManager.getService(Context.ALARM_SERVICE));
1715 }
1716 return mAppBindArgs;
1717 }
1718
1719 private final void setFocusedActivityLocked(HistoryRecord r) {
1720 if (mFocusedActivity != r) {
1721 mFocusedActivity = r;
1722 mWindowManager.setFocusedApp(r, true);
1723 }
1724 }
1725
Dianne Hackborn906497c2010-05-10 15:57:38 -07001726 private final void updateLruProcessInternalLocked(ProcessRecord app,
1727 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001729 int lrui = mLruProcesses.indexOf(app);
1730 if (lrui >= 0) mLruProcesses.remove(lrui);
1731
1732 int i = mLruProcesses.size()-1;
1733 int skipTop = 0;
1734
Dianne Hackborn906497c2010-05-10 15:57:38 -07001735 app.lruSeq = mLruSeq;
1736
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001737 // compute the new weight for this process.
1738 if (updateActivityTime) {
1739 app.lastActivityTime = SystemClock.uptimeMillis();
1740 }
1741 if (app.activities.size() > 0) {
1742 // If this process has activities, we more strongly want to keep
1743 // it around.
1744 app.lruWeight = app.lastActivityTime;
1745 } else if (app.pubProviders.size() > 0) {
1746 // If this process contains content providers, we want to keep
1747 // it a little more strongly.
1748 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1749 // Also don't let it kick out the first few "real" hidden processes.
1750 skipTop = MIN_HIDDEN_APPS;
1751 } else {
1752 // If this process doesn't have activities, we less strongly
1753 // want to keep it around, and generally want to avoid getting
1754 // in front of any very recently used activities.
1755 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1756 // Also don't let it kick out the first few "real" hidden processes.
1757 skipTop = MIN_HIDDEN_APPS;
1758 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001759
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001760 while (i >= 0) {
1761 ProcessRecord p = mLruProcesses.get(i);
1762 // If this app shouldn't be in front of the first N background
1763 // apps, then skip over that many that are currently hidden.
1764 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1765 skipTop--;
1766 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001767 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001768 mLruProcesses.add(i+1, app);
1769 break;
1770 }
1771 i--;
1772 }
1773 if (i < 0) {
1774 mLruProcesses.add(0, app);
1775 }
1776
Dianne Hackborn906497c2010-05-10 15:57:38 -07001777 // If the app is currently using a content provider or service,
1778 // bump those processes as well.
1779 if (app.connections.size() > 0) {
1780 for (ConnectionRecord cr : app.connections) {
1781 if (cr.binding != null && cr.binding.service != null
1782 && cr.binding.service.app != null
1783 && cr.binding.service.app.lruSeq != mLruSeq) {
1784 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1785 updateActivityTime, i+1);
1786 }
1787 }
1788 }
1789 if (app.conProviders.size() > 0) {
1790 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1791 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1792 updateLruProcessInternalLocked(cpr.app, oomAdj,
1793 updateActivityTime, i+1);
1794 }
1795 }
1796 }
1797
Joe Onorato8a9b2202010-02-26 18:56:32 -08001798 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 if (oomAdj) {
1800 updateOomAdjLocked();
1801 }
1802 }
1803
Dianne Hackborn906497c2010-05-10 15:57:38 -07001804 private final void updateLruProcessLocked(ProcessRecord app,
1805 boolean oomAdj, boolean updateActivityTime) {
1806 mLruSeq++;
1807 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1808 }
1809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810 private final boolean updateLRUListLocked(HistoryRecord r) {
1811 final boolean hadit = mLRUActivities.remove(r);
1812 mLRUActivities.add(r);
1813 return hadit;
1814 }
1815
1816 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1817 int i = mHistory.size()-1;
1818 while (i >= 0) {
1819 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1820 if (!r.finishing && r != notTop) {
1821 return r;
1822 }
1823 i--;
1824 }
1825 return null;
1826 }
1827
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001828 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1829 int i = mHistory.size()-1;
1830 while (i >= 0) {
1831 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1832 if (!r.finishing && !r.delayedResume && r != notTop) {
1833 return r;
1834 }
1835 i--;
1836 }
1837 return null;
1838 }
1839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 /**
1841 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001842 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 *
1844 * @param token If non-null, any history records matching this token will be skipped.
1845 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1846 *
1847 * @return Returns the HistoryRecord of the next activity on the stack.
1848 */
1849 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1850 int i = mHistory.size()-1;
1851 while (i >= 0) {
1852 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1853 // Note: the taskId check depends on real taskId fields being non-zero
1854 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1855 return r;
1856 }
1857 i--;
1858 }
1859 return null;
1860 }
1861
1862 private final ProcessRecord getProcessRecordLocked(
1863 String processName, int uid) {
1864 if (uid == Process.SYSTEM_UID) {
1865 // The system gets to run in any process. If there are multiple
1866 // processes with the same uid, just pick the first (this
1867 // should never happen).
1868 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1869 processName);
1870 return procs != null ? procs.valueAt(0) : null;
1871 }
1872 ProcessRecord proc = mProcessNames.get(processName, uid);
1873 return proc;
1874 }
1875
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001876 private void ensurePackageDexOpt(String packageName) {
1877 IPackageManager pm = ActivityThread.getPackageManager();
1878 try {
1879 if (pm.performDexOpt(packageName)) {
1880 mDidDexOpt = true;
1881 }
1882 } catch (RemoteException e) {
1883 }
1884 }
1885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 private boolean isNextTransitionForward() {
1887 int transit = mWindowManager.getPendingAppTransition();
1888 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1889 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1890 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1891 }
1892
1893 private final boolean realStartActivityLocked(HistoryRecord r,
1894 ProcessRecord app, boolean andResume, boolean checkConfig)
1895 throws RemoteException {
1896
1897 r.startFreezingScreenLocked(app, 0);
1898 mWindowManager.setAppVisibility(r, true);
1899
1900 // Have the window manager re-evaluate the orientation of
1901 // the screen based on the new activity order. Note that
1902 // as a result of this, it can call back into the activity
1903 // manager with a new orientation. We don't care about that,
1904 // because the activity is not currently running so we are
1905 // just restarting it anyway.
1906 if (checkConfig) {
1907 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001908 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909 r.mayFreezeScreenLocked(app) ? r : null);
1910 updateConfigurationLocked(config, r);
1911 }
1912
1913 r.app = app;
1914
Joe Onorato8a9b2202010-02-26 18:56:32 -08001915 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001916
1917 int idx = app.activities.indexOf(r);
1918 if (idx < 0) {
1919 app.activities.add(r);
1920 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001921 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922
1923 try {
1924 if (app.thread == null) {
1925 throw new RemoteException();
1926 }
1927 List<ResultInfo> results = null;
1928 List<Intent> newIntents = null;
1929 if (andResume) {
1930 results = r.results;
1931 newIntents = r.newIntents;
1932 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001933 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 + " icicle=" + r.icicle
1935 + " with results=" + results + " newIntents=" + newIntents
1936 + " andResume=" + andResume);
1937 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001938 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 System.identityHashCode(r),
1940 r.task.taskId, r.shortComponentName);
1941 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001942 if (r.isHomeActivity) {
1943 mHomeProcess = app;
1944 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001945 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001947 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001948 r.info, r.icicle, results, newIntents, !andResume,
1949 isNextTransitionForward());
Dianne Hackborn860755f2010-06-03 18:47:52 -07001950
1951 if ((app.info.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
1952 // This may be a heavy-weight process! Note that the package
1953 // manager will ensure that only activity can run in the main
1954 // process of the .apk, which is the only thing that will be
1955 // considered heavy-weight.
1956 if (app.processName.equals(app.info.packageName)) {
1957 if (mHeavyWeightProcess != null && mHeavyWeightProcess != app) {
1958 Log.w(TAG, "Starting new heavy weight process " + app
1959 + " when already running " + mHeavyWeightProcess);
1960 }
1961 mHeavyWeightProcess = app;
1962 Message msg = mHandler.obtainMessage(POST_HEAVY_NOTIFICATION_MSG);
1963 msg.obj = r;
1964 mHandler.sendMessage(msg);
1965 }
1966 }
1967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001968 } catch (RemoteException e) {
1969 if (r.launchFailed) {
1970 // This is the second time we failed -- finish activity
1971 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001972 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001973 + r.intent.getComponent().flattenToShortString()
1974 + ", giving up", e);
1975 appDiedLocked(app, app.pid, app.thread);
1976 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1977 "2nd-crash");
1978 return false;
1979 }
1980
1981 // This is the first time we failed -- restart process and
1982 // retry.
1983 app.activities.remove(r);
1984 throw e;
1985 }
1986
1987 r.launchFailed = false;
1988 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001989 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 + " being launched, but already in LRU list");
1991 }
1992
1993 if (andResume) {
1994 // As part of the process of launching, ActivityThread also performs
1995 // a resume.
1996 r.state = ActivityState.RESUMED;
1997 r.icicle = null;
1998 r.haveState = false;
1999 r.stopped = false;
2000 mResumedActivity = r;
2001 r.task.touchActiveTime();
2002 completeResumeLocked(r);
2003 pauseIfSleepingLocked();
2004 } else {
2005 // This activity is not starting in the resumed state... which
2006 // should look like we asked it to pause+stop (but remain visible),
2007 // and it has done so and reported back the current icicle and
2008 // other state.
2009 r.state = ActivityState.STOPPED;
2010 r.stopped = true;
2011 }
2012
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002013 // Launch the new version setup screen if needed. We do this -after-
2014 // launching the initial activity (that is, home), so that it can have
2015 // a chance to initialize itself while in the background, making the
2016 // switch back to it faster and look better.
2017 startSetupActivityLocked();
2018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019 return true;
2020 }
2021
2022 private final void startSpecificActivityLocked(HistoryRecord r,
2023 boolean andResume, boolean checkConfig) {
2024 // Is this activity's application already running?
2025 ProcessRecord app = getProcessRecordLocked(r.processName,
2026 r.info.applicationInfo.uid);
2027
2028 if (r.startTime == 0) {
2029 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002030 if (mInitialStartTime == 0) {
2031 mInitialStartTime = r.startTime;
2032 }
2033 } else if (mInitialStartTime == 0) {
2034 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035 }
2036
2037 if (app != null && app.thread != null) {
2038 try {
2039 realStartActivityLocked(r, app, andResume, checkConfig);
2040 return;
2041 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002042 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 + r.intent.getComponent().flattenToShortString(), e);
2044 }
2045
2046 // If a dead object exception was thrown -- fall through to
2047 // restart the application.
2048 }
2049
2050 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002051 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002052 }
2053
2054 private final ProcessRecord startProcessLocked(String processName,
2055 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002056 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
2058 // We don't have to do anything more if:
2059 // (1) There is an existing application record; and
2060 // (2) The caller doesn't think it is dead, OR there is no thread
2061 // object attached to it so we know it couldn't have crashed; and
2062 // (3) There is a pid assigned to it, so it is either starting or
2063 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002064 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 + " app=" + app + " knownToBeDead=" + knownToBeDead
2066 + " thread=" + (app != null ? app.thread : null)
2067 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01002068 if (app != null && app.pid > 0) {
2069 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002070 // We already have the app running, or are waiting for it to
2071 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01002072 return app;
2073 } else {
2074 // An application record is attached to a previous process,
2075 // clean it up now.
2076 handleAppDiedLocked(app, true);
2077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002080 String hostingNameStr = hostingName != null
2081 ? hostingName.flattenToShortString() : null;
2082
2083 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
2084 // If we are in the background, then check to see if this process
2085 // is bad. If so, we will just silently fail.
2086 if (mBadProcesses.get(info.processName, info.uid) != null) {
2087 return null;
2088 }
2089 } else {
2090 // When the user is explicitly starting a process, then clear its
2091 // crash count so that we won't make it bad until they see at
2092 // least one crash dialog again, and make the process good again
2093 // if it had been bad.
2094 mProcessCrashTimes.remove(info.processName, info.uid);
2095 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002096 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 info.processName);
2098 mBadProcesses.remove(info.processName, info.uid);
2099 if (app != null) {
2100 app.bad = false;
2101 }
2102 }
2103 }
2104
2105 if (app == null) {
2106 app = newProcessRecordLocked(null, info, processName);
2107 mProcessNames.put(processName, info.uid, app);
2108 } else {
2109 // If this is a new package in the process, add the package to the list
2110 app.addPackage(info.packageName);
2111 }
2112
2113 // If the system is not ready yet, then hold off on starting this
2114 // process until it is.
2115 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002116 && !isAllowedWhileBooting(info)
2117 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 if (!mProcessesOnHold.contains(app)) {
2119 mProcessesOnHold.add(app);
2120 }
2121 return app;
2122 }
2123
2124 startProcessLocked(app, hostingType, hostingNameStr);
2125 return (app.pid != 0) ? app : null;
2126 }
2127
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002128 boolean isAllowedWhileBooting(ApplicationInfo ai) {
2129 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
2130 }
2131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 private final void startProcessLocked(ProcessRecord app,
2133 String hostingType, String hostingNameStr) {
2134 if (app.pid > 0 && app.pid != MY_PID) {
2135 synchronized (mPidsSelfLocked) {
2136 mPidsSelfLocked.remove(app.pid);
2137 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
2138 }
2139 app.pid = 0;
2140 }
2141
2142 mProcessesOnHold.remove(app);
2143
2144 updateCpuStats();
2145
2146 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
2147 mProcDeaths[0] = 0;
2148
2149 try {
2150 int uid = app.info.uid;
2151 int[] gids = null;
2152 try {
2153 gids = mContext.getPackageManager().getPackageGids(
2154 app.info.packageName);
2155 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002156 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 }
2158 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
2159 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2160 && mTopComponent != null
2161 && app.processName.equals(mTopComponent.getPackageName())) {
2162 uid = 0;
2163 }
2164 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
2165 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
2166 uid = 0;
2167 }
2168 }
2169 int debugFlags = 0;
2170 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
2171 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
2172 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08002173 // Run the app in safe mode if its manifest requests so or the
2174 // system is booted in safe mode.
2175 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
2176 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08002177 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
2178 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
2180 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
2181 }
2182 if ("1".equals(SystemProperties.get("debug.assert"))) {
2183 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2184 }
2185 int pid = Process.start("android.app.ActivityThread",
2186 mSimpleProcessManagement ? app.processName : null, uid, uid,
2187 gids, debugFlags, null);
2188 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2189 synchronized (bs) {
2190 if (bs.isOnBattery()) {
2191 app.batteryStats.incStartsLocked();
2192 }
2193 }
2194
Doug Zongker2bec3d42009-12-04 12:52:44 -08002195 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 app.processName, hostingType,
2197 hostingNameStr != null ? hostingNameStr : "");
2198
2199 if (app.persistent) {
2200 Watchdog.getInstance().processStarted(app, app.processName, pid);
2201 }
2202
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002203 StringBuilder buf = mStringBuilder;
2204 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002205 buf.append("Start proc ");
2206 buf.append(app.processName);
2207 buf.append(" for ");
2208 buf.append(hostingType);
2209 if (hostingNameStr != null) {
2210 buf.append(" ");
2211 buf.append(hostingNameStr);
2212 }
2213 buf.append(": pid=");
2214 buf.append(pid);
2215 buf.append(" uid=");
2216 buf.append(uid);
2217 buf.append(" gids={");
2218 if (gids != null) {
2219 for (int gi=0; gi<gids.length; gi++) {
2220 if (gi != 0) buf.append(", ");
2221 buf.append(gids[gi]);
2222
2223 }
2224 }
2225 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002226 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 if (pid == 0 || pid == MY_PID) {
2228 // Processes are being emulated with threads.
2229 app.pid = MY_PID;
2230 app.removed = false;
2231 mStartingProcesses.add(app);
2232 } else if (pid > 0) {
2233 app.pid = pid;
2234 app.removed = false;
2235 synchronized (mPidsSelfLocked) {
2236 this.mPidsSelfLocked.put(pid, app);
2237 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2238 msg.obj = app;
2239 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2240 }
2241 } else {
2242 app.pid = 0;
2243 RuntimeException e = new RuntimeException(
2244 "Failure starting process " + app.processName
2245 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002246 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 }
2248 } catch (RuntimeException e) {
2249 // XXX do better error recovery.
2250 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002251 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 }
2253 }
2254
2255 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2256 if (mPausingActivity != null) {
2257 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002258 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 + mPausingActivity, e);
2260 }
2261 HistoryRecord prev = mResumedActivity;
2262 if (prev == null) {
2263 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002264 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002265 resumeTopActivityLocked(null);
2266 return;
2267 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002268 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 mResumedActivity = null;
2270 mPausingActivity = prev;
2271 mLastPausedActivity = prev;
2272 prev.state = ActivityState.PAUSING;
2273 prev.task.touchActiveTime();
2274
2275 updateCpuStats();
2276
2277 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002278 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002280 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002281 System.identityHashCode(prev),
2282 prev.shortComponentName);
2283 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2284 prev.configChangeFlags);
2285 updateUsageStats(prev, false);
2286 } catch (Exception e) {
2287 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002288 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289 mPausingActivity = null;
2290 mLastPausedActivity = null;
2291 }
2292 } else {
2293 mPausingActivity = null;
2294 mLastPausedActivity = null;
2295 }
2296
2297 // If we are not going to sleep, we want to ensure the device is
2298 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002299 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002300 mLaunchingActivity.acquire();
2301 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2302 // To be safe, don't allow the wake lock to be held for too long.
2303 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2304 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2305 }
2306 }
2307
2308
2309 if (mPausingActivity != null) {
2310 // Have the window manager pause its key dispatching until the new
2311 // activity has started. If we're pausing the activity just because
2312 // the screen is being turned off and the UI is sleeping, don't interrupt
2313 // key dispatch; the same activity will pick it up again on wakeup.
2314 if (!uiSleeping) {
2315 prev.pauseKeyDispatchingLocked();
2316 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002317 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 }
2319
2320 // Schedule a pause timeout in case the app doesn't respond.
2321 // We don't give it much time because this directly impacts the
2322 // responsiveness seen by the user.
2323 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2324 msg.obj = prev;
2325 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002326 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002327 } else {
2328 // This activity failed to schedule the
2329 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002330 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 resumeTopActivityLocked(null);
2332 }
2333 }
2334
2335 private final void completePauseLocked() {
2336 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002337 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338
2339 if (prev != null) {
2340 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002341 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002342 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2343 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002344 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002345 if (prev.waitingVisible) {
2346 prev.waitingVisible = false;
2347 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002348 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002349 TAG, "Complete pause, no longer waiting: " + prev);
2350 }
2351 if (prev.configDestroy) {
2352 // The previous is being paused because the configuration
2353 // is changing, which means it is actually stopping...
2354 // To juggle the fact that we are also starting a new
2355 // instance right now, we need to first completely stop
2356 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002357 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 destroyActivityLocked(prev, true);
2359 } else {
2360 mStoppingActivities.add(prev);
2361 if (mStoppingActivities.size() > 3) {
2362 // If we already have a few activities waiting to stop,
2363 // then give up on things going idle and start clearing
2364 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002365 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002366 Message msg = Message.obtain();
2367 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2368 mHandler.sendMessage(msg);
2369 }
2370 }
2371 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002372 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 prev = null;
2374 }
2375 mPausingActivity = null;
2376 }
2377
Dianne Hackborn55280a92009-05-07 15:53:46 -07002378 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 resumeTopActivityLocked(prev);
2380 } else {
2381 if (mGoingToSleep.isHeld()) {
2382 mGoingToSleep.release();
2383 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002384 if (mShuttingDown) {
2385 notifyAll();
2386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 }
2388
2389 if (prev != null) {
2390 prev.resumeKeyDispatchingLocked();
2391 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002392
2393 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2394 long diff = 0;
2395 synchronized (mProcessStatsThread) {
2396 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2397 }
2398 if (diff > 0) {
2399 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2400 synchronized (bsi) {
2401 BatteryStatsImpl.Uid.Proc ps =
2402 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2403 prev.info.packageName);
2404 if (ps != null) {
2405 ps.addForegroundTimeLocked(diff);
2406 }
2407 }
2408 }
2409 }
2410 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002411 }
2412
2413 /**
2414 * Once we know that we have asked an application to put an activity in
2415 * the resumed state (either by launching it or explicitly telling it),
2416 * this function updates the rest of our state to match that fact.
2417 */
2418 private final void completeResumeLocked(HistoryRecord next) {
2419 next.idle = false;
2420 next.results = null;
2421 next.newIntents = null;
2422
2423 // schedule an idle timeout in case the app doesn't do it for us.
2424 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2425 msg.obj = next;
2426 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2427
2428 if (false) {
2429 // The activity was never told to pause, so just keep
2430 // things going as-is. To maintain our own state,
2431 // we need to emulate it coming back and saying it is
2432 // idle.
2433 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2434 msg.obj = next;
2435 mHandler.sendMessage(msg);
2436 }
2437
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002438 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002440 next.thumbnail = null;
2441 setFocusedActivityLocked(next);
2442 next.resumeKeyDispatchingLocked();
2443 ensureActivitiesVisibleLocked(null, 0);
2444 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002445 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002446
2447 // Mark the point when the activity is resuming
2448 // TODO: To be more accurate, the mark should be before the onCreate,
2449 // not after the onResume. But for subsequent starts, onResume is fine.
2450 if (next.app != null) {
2451 synchronized (mProcessStatsThread) {
2452 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2453 }
2454 } else {
2455 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002457 }
2458
2459 /**
2460 * Make sure that all activities that need to be visible (that is, they
2461 * currently can be seen by the user) actually are.
2462 */
2463 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2464 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002465 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002466 TAG, "ensureActivitiesVisible behind " + top
2467 + " configChanges=0x" + Integer.toHexString(configChanges));
2468
2469 // If the top activity is not fullscreen, then we need to
2470 // make sure any activities under it are now visible.
2471 final int count = mHistory.size();
2472 int i = count-1;
2473 while (mHistory.get(i) != top) {
2474 i--;
2475 }
2476 HistoryRecord r;
2477 boolean behindFullscreen = false;
2478 for (; i>=0; i--) {
2479 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002480 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002481 TAG, "Make visible? " + r + " finishing=" + r.finishing
2482 + " state=" + r.state);
2483 if (r.finishing) {
2484 continue;
2485 }
2486
2487 final boolean doThisProcess = onlyThisProcess == null
2488 || onlyThisProcess.equals(r.processName);
2489
2490 // First: if this is not the current activity being started, make
2491 // sure it matches the current configuration.
2492 if (r != starting && doThisProcess) {
2493 ensureActivityConfigurationLocked(r, 0);
2494 }
2495
2496 if (r.app == null || r.app.thread == null) {
2497 if (onlyThisProcess == null
2498 || onlyThisProcess.equals(r.processName)) {
2499 // This activity needs to be visible, but isn't even
2500 // running... get it started, but don't resume it
2501 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002502 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002503 TAG, "Start and freeze screen for " + r);
2504 if (r != starting) {
2505 r.startFreezingScreenLocked(r.app, configChanges);
2506 }
2507 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002508 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 TAG, "Starting and making visible: " + r);
2510 mWindowManager.setAppVisibility(r, true);
2511 }
2512 if (r != starting) {
2513 startSpecificActivityLocked(r, false, false);
2514 }
2515 }
2516
2517 } else if (r.visible) {
2518 // If this activity is already visible, then there is nothing
2519 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002520 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521 TAG, "Skipping: already visible at " + r);
2522 r.stopFreezingScreenLocked(false);
2523
2524 } else if (onlyThisProcess == null) {
2525 // This activity is not currently visible, but is running.
2526 // Tell it to become visible.
2527 r.visible = true;
2528 if (r.state != ActivityState.RESUMED && r != starting) {
2529 // If this activity is paused, tell it
2530 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002531 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 TAG, "Making visible and scheduling visibility: " + r);
2533 try {
2534 mWindowManager.setAppVisibility(r, true);
2535 r.app.thread.scheduleWindowVisibility(r, true);
2536 r.stopFreezingScreenLocked(false);
2537 } catch (Exception e) {
2538 // Just skip on any failure; we'll make it
2539 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002540 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002541 + r.intent.getComponent(), e);
2542 }
2543 }
2544 }
2545
2546 // Aggregate current change flags.
2547 configChanges |= r.configChangeFlags;
2548
2549 if (r.fullscreen) {
2550 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002551 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 TAG, "Stopping: fullscreen at " + r);
2553 behindFullscreen = true;
2554 i--;
2555 break;
2556 }
2557 }
2558
2559 // Now for any activities that aren't visible to the user, make
2560 // sure they no longer are keeping the screen frozen.
2561 while (i >= 0) {
2562 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002563 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002564 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2565 + " state=" + r.state
2566 + " behindFullscreen=" + behindFullscreen);
2567 if (!r.finishing) {
2568 if (behindFullscreen) {
2569 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002570 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 TAG, "Making invisible: " + r);
2572 r.visible = false;
2573 try {
2574 mWindowManager.setAppVisibility(r, false);
2575 if ((r.state == ActivityState.STOPPING
2576 || r.state == ActivityState.STOPPED)
2577 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002578 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002579 TAG, "Scheduling invisibility: " + r);
2580 r.app.thread.scheduleWindowVisibility(r, false);
2581 }
2582 } catch (Exception e) {
2583 // Just skip on any failure; we'll make it
2584 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002585 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 + r.intent.getComponent(), e);
2587 }
2588 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002589 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 TAG, "Already invisible: " + r);
2591 }
2592 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002593 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 TAG, "Now behindFullscreen: " + r);
2595 behindFullscreen = true;
2596 }
2597 }
2598 i--;
2599 }
2600 }
2601
2602 /**
2603 * Version of ensureActivitiesVisible that can easily be called anywhere.
2604 */
2605 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2606 int configChanges) {
2607 HistoryRecord r = topRunningActivityLocked(null);
2608 if (r != null) {
2609 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2610 }
2611 }
2612
2613 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2614 if (resumed) {
2615 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2616 } else {
2617 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2618 }
2619 }
2620
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002621 private boolean startHomeActivityLocked() {
2622 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2623 && mTopAction == null) {
2624 // We are running in factory test mode, but unable to find
2625 // the factory test app, so just sit around displaying the
2626 // error message and don't try to start anything.
2627 return false;
2628 }
2629 Intent intent = new Intent(
2630 mTopAction,
2631 mTopData != null ? Uri.parse(mTopData) : null);
2632 intent.setComponent(mTopComponent);
2633 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2634 intent.addCategory(Intent.CATEGORY_HOME);
2635 }
2636 ActivityInfo aInfo =
2637 intent.resolveActivityInfo(mContext.getPackageManager(),
2638 STOCK_PM_FLAGS);
2639 if (aInfo != null) {
2640 intent.setComponent(new ComponentName(
2641 aInfo.applicationInfo.packageName, aInfo.name));
2642 // Don't do this if the home app is currently being
2643 // instrumented.
2644 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2645 aInfo.applicationInfo.uid);
2646 if (app == null || app.instrumentationClass == null) {
2647 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2648 startActivityLocked(null, intent, null, null, 0, aInfo,
2649 null, null, 0, 0, 0, false, false);
2650 }
2651 }
2652
2653
2654 return true;
2655 }
2656
2657 /**
2658 * Starts the "new version setup screen" if appropriate.
2659 */
2660 private void startSetupActivityLocked() {
2661 // Only do this once per boot.
2662 if (mCheckedForSetup) {
2663 return;
2664 }
2665
2666 // We will show this screen if the current one is a different
2667 // version than the last one shown, and we are not running in
2668 // low-level factory test mode.
2669 final ContentResolver resolver = mContext.getContentResolver();
2670 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2671 Settings.Secure.getInt(resolver,
2672 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2673 mCheckedForSetup = true;
2674
2675 // See if we should be showing the platform update setup UI.
2676 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2677 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2678 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2679
2680 // We don't allow third party apps to replace this.
2681 ResolveInfo ri = null;
2682 for (int i=0; ris != null && i<ris.size(); i++) {
2683 if ((ris.get(i).activityInfo.applicationInfo.flags
2684 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2685 ri = ris.get(i);
2686 break;
2687 }
2688 }
2689
2690 if (ri != null) {
2691 String vers = ri.activityInfo.metaData != null
2692 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2693 : null;
2694 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2695 vers = ri.activityInfo.applicationInfo.metaData.getString(
2696 Intent.METADATA_SETUP_VERSION);
2697 }
2698 String lastVers = Settings.Secure.getString(
2699 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2700 if (vers != null && !vers.equals(lastVers)) {
2701 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2702 intent.setComponent(new ComponentName(
2703 ri.activityInfo.packageName, ri.activityInfo.name));
2704 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2705 null, null, 0, 0, 0, false, false);
2706 }
2707 }
2708 }
2709 }
2710
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002711 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002712 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002713
2714 final int identHash = System.identityHashCode(r);
2715 updateUsageStats(r, true);
2716
2717 int i = mWatchers.beginBroadcast();
2718 while (i > 0) {
2719 i--;
2720 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2721 if (w != null) {
2722 try {
2723 w.activityResuming(identHash);
2724 } catch (RemoteException e) {
2725 }
2726 }
2727 }
2728 mWatchers.finishBroadcast();
2729 }
2730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 /**
2732 * Ensure that the top activity in the stack is resumed.
2733 *
2734 * @param prev The previously resumed activity, for when in the process
2735 * of pausing; can be null to call from elsewhere.
2736 *
2737 * @return Returns true if something is being resumed, or false if
2738 * nothing happened.
2739 */
2740 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2741 // Find the first activity that is not finishing.
2742 HistoryRecord next = topRunningActivityLocked(null);
2743
2744 // Remember how we'll process this pause/resume situation, and ensure
2745 // that the state is reset however we wind up proceeding.
2746 final boolean userLeaving = mUserLeaving;
2747 mUserLeaving = false;
2748
2749 if (next == null) {
2750 // There are no more activities! Let's just start up the
2751 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002752 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002753 }
2754
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002755 next.delayedResume = false;
2756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002757 // If the top activity is the resumed one, nothing to do.
2758 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2759 // Make sure we have executed any pending transitions, since there
2760 // should be nothing left to do at this point.
2761 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002762 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763 return false;
2764 }
2765
2766 // If we are sleeping, and there is no resumed activity, and the top
2767 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002768 if ((mSleeping || mShuttingDown)
2769 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002770 // Make sure we have executed any pending transitions, since there
2771 // should be nothing left to do at this point.
2772 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002773 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002774 return false;
2775 }
2776
2777 // The activity may be waiting for stop, but that is no longer
2778 // appropriate for it.
2779 mStoppingActivities.remove(next);
2780 mWaitingVisibleActivities.remove(next);
2781
Joe Onorato8a9b2202010-02-26 18:56:32 -08002782 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002783
2784 // If we are currently pausing an activity, then don't do anything
2785 // until that is done.
2786 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002787 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002788 return false;
2789 }
2790
2791 // We need to start pausing the current activity so the top one
2792 // can be resumed...
2793 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002794 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 startPausingLocked(userLeaving, false);
2796 return true;
2797 }
2798
2799 if (prev != null && prev != next) {
2800 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2801 prev.waitingVisible = true;
2802 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002803 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002804 TAG, "Resuming top, waiting visible to hide: " + prev);
2805 } else {
2806 // The next activity is already visible, so hide the previous
2807 // activity's windows right now so we can show the new one ASAP.
2808 // We only do this if the previous is finishing, which should mean
2809 // it is on top of the one being resumed so hiding it quickly
2810 // is good. Otherwise, we want to do the normal route of allowing
2811 // the resumed activity to be shown so we can decide if the
2812 // previous should actually be hidden depending on whether the
2813 // new one is found to be full-screen or not.
2814 if (prev.finishing) {
2815 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002816 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817 + prev + ", waitingVisible="
2818 + (prev != null ? prev.waitingVisible : null)
2819 + ", nowVisible=" + next.nowVisible);
2820 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002821 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002822 + prev + ", waitingVisible="
2823 + (prev != null ? prev.waitingVisible : null)
2824 + ", nowVisible=" + next.nowVisible);
2825 }
2826 }
2827 }
2828
2829 // We are starting up the next activity, so tell the window manager
2830 // that the previous one will be hidden soon. This way it can know
2831 // to ignore it when computing the desired screen orientation.
2832 if (prev != null) {
2833 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002834 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002835 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002836 if (mNoAnimActivities.contains(prev)) {
2837 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2838 } else {
2839 mWindowManager.prepareAppTransition(prev.task == next.task
2840 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2841 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2842 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002843 mWindowManager.setAppWillBeHidden(prev);
2844 mWindowManager.setAppVisibility(prev, false);
2845 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002846 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002847 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002848 if (mNoAnimActivities.contains(next)) {
2849 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2850 } else {
2851 mWindowManager.prepareAppTransition(prev.task == next.task
2852 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2853 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2854 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002855 }
2856 if (false) {
2857 mWindowManager.setAppWillBeHidden(prev);
2858 mWindowManager.setAppVisibility(prev, false);
2859 }
2860 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002861 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002862 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002863 if (mNoAnimActivities.contains(next)) {
2864 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2865 } else {
2866 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002868 }
2869
2870 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002871 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872
2873 // This activity is now becoming visible.
2874 mWindowManager.setAppVisibility(next, true);
2875
2876 HistoryRecord lastResumedActivity = mResumedActivity;
2877 ActivityState lastState = next.state;
2878
2879 updateCpuStats();
2880
2881 next.state = ActivityState.RESUMED;
2882 mResumedActivity = next;
2883 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002884 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002885 updateLRUListLocked(next);
2886
2887 // Have the window manager re-evaluate the orientation of
2888 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002889 boolean updated;
2890 synchronized (this) {
2891 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2892 mConfiguration,
2893 next.mayFreezeScreenLocked(next.app) ? next : null);
2894 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002895 next.frozenBeforeDestroy = true;
2896 }
2897 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002898 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002899 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 // The configuration update wasn't able to keep the existing
2901 // instance of the activity, and instead started a new one.
2902 // We should be all done, but let's just make sure our activity
2903 // is still at the top and schedule another run if something
2904 // weird happened.
2905 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002906 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002907 "Activity config changed during resume: " + next
2908 + ", new next: " + nextNext);
2909 if (nextNext != next) {
2910 // Do over!
2911 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2912 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002913 setFocusedActivityLocked(next);
2914 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002915 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002916 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002917 return true;
2918 }
2919
2920 try {
2921 // Deliver all pending results.
2922 ArrayList a = next.results;
2923 if (a != null) {
2924 final int N = a.size();
2925 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002926 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002927 TAG, "Delivering results to " + next
2928 + ": " + a);
2929 next.app.thread.scheduleSendResult(next, a);
2930 }
2931 }
2932
2933 if (next.newIntents != null) {
2934 next.app.thread.scheduleNewIntent(next.newIntents, next);
2935 }
2936
Doug Zongker2bec3d42009-12-04 12:52:44 -08002937 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 System.identityHashCode(next),
2939 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940
2941 next.app.thread.scheduleResumeActivity(next,
2942 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 pauseIfSleepingLocked();
2945
2946 } catch (Exception e) {
2947 // Whoops, need to restart this activity!
2948 next.state = lastState;
2949 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002950 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 if (!next.hasBeenLaunched) {
2952 next.hasBeenLaunched = true;
2953 } else {
2954 if (SHOW_APP_STARTING_ICON) {
2955 mWindowManager.setAppStartingWindow(
2956 next, next.packageName, next.theme,
2957 next.nonLocalizedLabel,
2958 next.labelRes, next.icon, null, true);
2959 }
2960 }
2961 startSpecificActivityLocked(next, true, false);
2962 return true;
2963 }
2964
2965 // From this point on, if something goes wrong there is no way
2966 // to recover the activity.
2967 try {
2968 next.visible = true;
2969 completeResumeLocked(next);
2970 } catch (Exception e) {
2971 // If any exception gets thrown, toss away this
2972 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002973 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002974 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2975 "resume-exception");
2976 return true;
2977 }
2978
2979 // Didn't need to use the icicle, and it is now out of date.
2980 next.icicle = null;
2981 next.haveState = false;
2982 next.stopped = false;
2983
2984 } else {
2985 // Whoops, need to restart this activity!
2986 if (!next.hasBeenLaunched) {
2987 next.hasBeenLaunched = true;
2988 } else {
2989 if (SHOW_APP_STARTING_ICON) {
2990 mWindowManager.setAppStartingWindow(
2991 next, next.packageName, next.theme,
2992 next.nonLocalizedLabel,
2993 next.labelRes, next.icon, null, true);
2994 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002995 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002996 }
2997 startSpecificActivityLocked(next, true, true);
2998 }
2999
3000 return true;
3001 }
3002
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003003 private final void startActivityLocked(HistoryRecord r, boolean newTask,
3004 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003005 final int NH = mHistory.size();
3006
3007 int addPos = -1;
3008
3009 if (!newTask) {
3010 // If starting in an existing task, find where that is...
3011 HistoryRecord next = null;
3012 boolean startIt = true;
3013 for (int i = NH-1; i >= 0; i--) {
3014 HistoryRecord p = (HistoryRecord)mHistory.get(i);
3015 if (p.finishing) {
3016 continue;
3017 }
3018 if (p.task == r.task) {
3019 // Here it is! Now, if this is not yet visible to the
3020 // user, then just add it without starting; it will
3021 // get started when the user navigates back to it.
3022 addPos = i+1;
3023 if (!startIt) {
3024 mHistory.add(addPos, r);
3025 r.inHistory = true;
3026 r.task.numActivities++;
3027 mWindowManager.addAppToken(addPos, r, r.task.taskId,
3028 r.info.screenOrientation, r.fullscreen);
3029 if (VALIDATE_TOKENS) {
3030 mWindowManager.validateAppTokens(mHistory);
3031 }
3032 return;
3033 }
3034 break;
3035 }
3036 if (p.fullscreen) {
3037 startIt = false;
3038 }
3039 next = p;
3040 }
3041 }
3042
3043 // Place a new activity at top of stack, so it is next to interact
3044 // with the user.
3045 if (addPos < 0) {
3046 addPos = mHistory.size();
3047 }
3048
3049 // If we are not placing the new activity frontmost, we do not want
3050 // to deliver the onUserLeaving callback to the actual frontmost
3051 // activity
3052 if (addPos < NH) {
3053 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003054 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 }
3056
3057 // Slot the activity into the history stack and proceed
3058 mHistory.add(addPos, r);
3059 r.inHistory = true;
3060 r.frontOfTask = newTask;
3061 r.task.numActivities++;
3062 if (NH > 0) {
3063 // We want to show the starting preview window if we are
3064 // switching to a new task, or the next activity's process is
3065 // not currently running.
3066 boolean showStartingIcon = newTask;
3067 ProcessRecord proc = r.app;
3068 if (proc == null) {
3069 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
3070 }
3071 if (proc == null || proc.thread == null) {
3072 showStartingIcon = true;
3073 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003074 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003076 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3077 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
3078 mNoAnimActivities.add(r);
3079 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3080 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
3081 mNoAnimActivities.remove(r);
3082 } else {
3083 mWindowManager.prepareAppTransition(newTask
3084 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
3085 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
3086 mNoAnimActivities.remove(r);
3087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003088 mWindowManager.addAppToken(
3089 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
3090 boolean doShow = true;
3091 if (newTask) {
3092 // Even though this activity is starting fresh, we still need
3093 // to reset it to make sure we apply affinities to move any
3094 // existing activities from other tasks in to it.
3095 // If the caller has requested that the target task be
3096 // reset, then do so.
3097 if ((r.intent.getFlags()
3098 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3099 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003100 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 }
3102 }
3103 if (SHOW_APP_STARTING_ICON && doShow) {
3104 // Figure out if we are transitioning from another activity that is
3105 // "has the same starting icon" as the next one. This allows the
3106 // window manager to keep the previous window it had previously
3107 // created, if it still had one.
3108 HistoryRecord prev = mResumedActivity;
3109 if (prev != null) {
3110 // We don't want to reuse the previous starting preview if:
3111 // (1) The current activity is in a different task.
3112 if (prev.task != r.task) prev = null;
3113 // (2) The current activity is already displayed.
3114 else if (prev.nowVisible) prev = null;
3115 }
3116 mWindowManager.setAppStartingWindow(
3117 r, r.packageName, r.theme, r.nonLocalizedLabel,
3118 r.labelRes, r.icon, prev, showStartingIcon);
3119 }
3120 } else {
3121 // If this is the first activity, don't do any fancy animations,
3122 // because there is nothing for it to animate on top of.
3123 mWindowManager.addAppToken(addPos, r, r.task.taskId,
3124 r.info.screenOrientation, r.fullscreen);
3125 }
3126 if (VALIDATE_TOKENS) {
3127 mWindowManager.validateAppTokens(mHistory);
3128 }
3129
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003130 if (doResume) {
3131 resumeTopActivityLocked(null);
3132 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003133 }
3134
3135 /**
3136 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003137 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
3138 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003139 * an instance of that activity in the stack and, if found, finish all
3140 * activities on top of it and return the instance.
3141 *
3142 * @param newR Description of the new activity being started.
3143 * @return Returns the old activity that should be continue to be used,
3144 * or null if none was found.
3145 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003146 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003147 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003148 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003149
3150 // First find the requested task.
3151 while (i > 0) {
3152 i--;
3153 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3154 if (r.task.taskId == taskId) {
3155 i++;
3156 break;
3157 }
3158 }
3159
3160 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003161 while (i > 0) {
3162 i--;
3163 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3164 if (r.finishing) {
3165 continue;
3166 }
3167 if (r.task.taskId != taskId) {
3168 return null;
3169 }
3170 if (r.realActivity.equals(newR.realActivity)) {
3171 // Here it is! Now finish everything in front...
3172 HistoryRecord ret = r;
3173 if (doClear) {
3174 while (i < (mHistory.size()-1)) {
3175 i++;
3176 r = (HistoryRecord)mHistory.get(i);
3177 if (r.finishing) {
3178 continue;
3179 }
3180 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3181 null, "clear")) {
3182 i--;
3183 }
3184 }
3185 }
3186
3187 // Finally, if this is a normal launch mode (that is, not
3188 // expecting onNewIntent()), then we will finish the current
3189 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003190 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
3191 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003192 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003193 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003194 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07003195 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003196 null, "clear");
3197 }
3198 return null;
3199 }
3200 }
3201
3202 return ret;
3203 }
3204 }
3205
3206 return null;
3207 }
3208
3209 /**
3210 * Find the activity in the history stack within the given task. Returns
3211 * the index within the history at which it's found, or < 0 if not found.
3212 */
3213 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3214 int i = mHistory.size();
3215 while (i > 0) {
3216 i--;
3217 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3218 if (candidate.task.taskId != task) {
3219 break;
3220 }
3221 if (candidate.realActivity.equals(r.realActivity)) {
3222 return i;
3223 }
3224 }
3225
3226 return -1;
3227 }
3228
3229 /**
3230 * Reorder the history stack so that the activity at the given index is
3231 * brought to the front.
3232 */
3233 private final HistoryRecord moveActivityToFrontLocked(int where) {
3234 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3235 int top = mHistory.size();
3236 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3237 mHistory.add(top, newTop);
3238 oldTop.frontOfTask = false;
3239 newTop.frontOfTask = true;
3240 return newTop;
3241 }
3242
3243 /**
3244 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3245 * method will be called at the proper time.
3246 */
3247 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3248 boolean sent = false;
3249 if (r.state == ActivityState.RESUMED
3250 && r.app != null && r.app.thread != null) {
3251 try {
3252 ArrayList<Intent> ar = new ArrayList<Intent>();
3253 ar.add(new Intent(intent));
3254 r.app.thread.scheduleNewIntent(ar, r);
3255 sent = true;
3256 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003257 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 }
3259 }
3260 if (!sent) {
3261 r.addNewIntentLocked(new Intent(intent));
3262 }
3263 }
3264
3265 private final void logStartActivity(int tag, HistoryRecord r,
3266 TaskRecord task) {
3267 EventLog.writeEvent(tag,
3268 System.identityHashCode(r), task.taskId,
3269 r.shortComponentName, r.intent.getAction(),
3270 r.intent.getType(), r.intent.getDataString(),
3271 r.intent.getFlags());
3272 }
3273
3274 private final int startActivityLocked(IApplicationThread caller,
3275 Intent intent, String resolvedType,
3276 Uri[] grantedUriPermissions,
3277 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3278 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003279 int callingPid, int callingUid, boolean onlyIfNeeded,
3280 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003281 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003282
3283 HistoryRecord sourceRecord = null;
3284 HistoryRecord resultRecord = null;
3285 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003286 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003287 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003288 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3289 if (index >= 0) {
3290 sourceRecord = (HistoryRecord)mHistory.get(index);
3291 if (requestCode >= 0 && !sourceRecord.finishing) {
3292 resultRecord = sourceRecord;
3293 }
3294 }
3295 }
3296
3297 int launchFlags = intent.getFlags();
3298
3299 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3300 && sourceRecord != null) {
3301 // Transfer the result target from the source activity to the new
3302 // one being started, including any failures.
3303 if (requestCode >= 0) {
3304 return START_FORWARD_AND_REQUEST_CONFLICT;
3305 }
3306 resultRecord = sourceRecord.resultTo;
3307 resultWho = sourceRecord.resultWho;
3308 requestCode = sourceRecord.requestCode;
3309 sourceRecord.resultTo = null;
3310 if (resultRecord != null) {
3311 resultRecord.removeResultsLocked(
3312 sourceRecord, resultWho, requestCode);
3313 }
3314 }
3315
3316 int err = START_SUCCESS;
3317
3318 if (intent.getComponent() == null) {
3319 // We couldn't find a class that can handle the given Intent.
3320 // That's the end of that!
3321 err = START_INTENT_NOT_RESOLVED;
3322 }
3323
3324 if (err == START_SUCCESS && aInfo == null) {
3325 // We couldn't find the specific class specified in the Intent.
3326 // Also the end of the line.
3327 err = START_CLASS_NOT_FOUND;
3328 }
3329
3330 ProcessRecord callerApp = null;
3331 if (err == START_SUCCESS && caller != null) {
3332 callerApp = getRecordForAppLocked(caller);
3333 if (callerApp != null) {
3334 callingPid = callerApp.pid;
3335 callingUid = callerApp.info.uid;
3336 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003337 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003338 + " (pid=" + callingPid + ") when starting: "
3339 + intent.toString());
3340 err = START_PERMISSION_DENIED;
3341 }
3342 }
3343
3344 if (err != START_SUCCESS) {
3345 if (resultRecord != null) {
3346 sendActivityResultLocked(-1,
3347 resultRecord, resultWho, requestCode,
3348 Activity.RESULT_CANCELED, null);
3349 }
3350 return err;
3351 }
3352
3353 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3354 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3355 if (perm != PackageManager.PERMISSION_GRANTED) {
3356 if (resultRecord != null) {
3357 sendActivityResultLocked(-1,
3358 resultRecord, resultWho, requestCode,
3359 Activity.RESULT_CANCELED, null);
3360 }
3361 String msg = "Permission Denial: starting " + intent.toString()
3362 + " from " + callerApp + " (pid=" + callingPid
3363 + ", uid=" + callingUid + ")"
3364 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003365 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366 throw new SecurityException(msg);
3367 }
3368
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003369 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 boolean abort = false;
3371 try {
3372 // The Intent we give to the watcher has the extra data
3373 // stripped off, since it can contain private information.
3374 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003375 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003376 aInfo.applicationInfo.packageName);
3377 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003378 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379 }
3380
3381 if (abort) {
3382 if (resultRecord != null) {
3383 sendActivityResultLocked(-1,
3384 resultRecord, resultWho, requestCode,
3385 Activity.RESULT_CANCELED, null);
3386 }
3387 // We pretend to the caller that it was really started, but
3388 // they will just get a cancel result.
3389 return START_SUCCESS;
3390 }
3391 }
3392
3393 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3394 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003395 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003396
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003397 if (mResumedActivity == null
3398 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3399 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3400 PendingActivityLaunch pal = new PendingActivityLaunch();
3401 pal.r = r;
3402 pal.sourceRecord = sourceRecord;
3403 pal.grantedUriPermissions = grantedUriPermissions;
3404 pal.grantedMode = grantedMode;
3405 pal.onlyIfNeeded = onlyIfNeeded;
3406 mPendingActivityLaunches.add(pal);
3407 return START_SWITCHES_CANCELED;
3408 }
3409 }
3410
3411 if (mDidAppSwitch) {
3412 // This is the second allowed switch since we stopped switches,
3413 // so now just generally allow switches. Use case: user presses
3414 // home (switches disabled, switch to home, mDidAppSwitch now true);
3415 // user taps a home icon (coming from home so allowed, we hit here
3416 // and now allow anyone to switch again).
3417 mAppSwitchesAllowedTime = 0;
3418 } else {
3419 mDidAppSwitch = true;
3420 }
3421
3422 doPendingActivityLaunchesLocked(false);
3423
3424 return startActivityUncheckedLocked(r, sourceRecord,
3425 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3426 }
3427
3428 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3429 final int N = mPendingActivityLaunches.size();
3430 if (N <= 0) {
3431 return;
3432 }
3433 for (int i=0; i<N; i++) {
3434 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3435 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3436 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3437 doResume && i == (N-1));
3438 }
3439 mPendingActivityLaunches.clear();
3440 }
3441
3442 private final int startActivityUncheckedLocked(HistoryRecord r,
3443 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3444 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3445 final Intent intent = r.intent;
3446 final int callingUid = r.launchedFromUid;
3447
3448 int launchFlags = intent.getFlags();
3449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 // We'll invoke onUserLeaving before onPause only if the launching
3451 // activity did not explicitly state that this is an automated launch.
3452 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003453 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 "startActivity() => mUserLeaving=" + mUserLeaving);
3455
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003456 // If the caller has asked not to resume at this point, we make note
3457 // of this in the record so that we can skip it when trying to find
3458 // the top running activity.
3459 if (!doResume) {
3460 r.delayedResume = true;
3461 }
3462
3463 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3464 != 0 ? r : null;
3465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003466 // If the onlyIfNeeded flag is set, then we can do this if the activity
3467 // being launched is the same as the one making the call... or, as
3468 // a special case, if we do not know the caller then we count the
3469 // current top activity as the caller.
3470 if (onlyIfNeeded) {
3471 HistoryRecord checkedCaller = sourceRecord;
3472 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003473 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 }
3475 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3476 // Caller is not the same as launcher, so always needed.
3477 onlyIfNeeded = false;
3478 }
3479 }
3480
3481 if (grantedUriPermissions != null && callingUid > 0) {
3482 for (int i=0; i<grantedUriPermissions.length; i++) {
3483 grantUriPermissionLocked(callingUid, r.packageName,
3484 grantedUriPermissions[i], grantedMode, r);
3485 }
3486 }
3487
3488 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3489 intent, r);
3490
3491 if (sourceRecord == null) {
3492 // This activity is not being started from another... in this
3493 // case we -always- start a new task.
3494 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003495 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 -08003496 + intent);
3497 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3498 }
3499 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3500 // The original activity who is starting us is running as a single
3501 // instance... this new activity it is starting must go on its
3502 // own task.
3503 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3504 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3505 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3506 // The activity being started is a single instance... it always
3507 // gets launched into its own task.
3508 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3509 }
3510
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003511 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003512 // For whatever reason this activity is being launched into a new
3513 // task... yet the caller has requested a result back. Well, that
3514 // is pretty messed up, so instead immediately send back a cancel
3515 // and let the new task continue launched as normal without a
3516 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003517 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003518 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003519 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520 Activity.RESULT_CANCELED, null);
3521 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003522 }
3523
3524 boolean addingToTask = false;
3525 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3526 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3527 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3528 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3529 // If bring to front is requested, and no result is requested, and
3530 // we can find a task that was started with this same
3531 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003532 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 // See if there is a task to bring to the front. If this is
3534 // a SINGLE_INSTANCE activity, there can be one and only one
3535 // instance of it in the history, and it is always in its own
3536 // unique task, so we do a special search.
3537 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3538 ? findTaskLocked(intent, r.info)
3539 : findActivityLocked(intent, r.info);
3540 if (taskTop != null) {
3541 if (taskTop.task.intent == null) {
3542 // This task was started because of movement of
3543 // the activity based on affinity... now that we
3544 // are actually launching it, we can assign the
3545 // base intent.
3546 taskTop.task.setIntent(intent, r.info);
3547 }
3548 // If the target task is not in the front, then we need
3549 // to bring it to the front... except... well, with
3550 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3551 // to have the same behavior as if a new instance was
3552 // being started, which means not bringing it to the front
3553 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003554 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003555 if (curTop.task != taskTop.task) {
3556 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3557 boolean callerAtFront = sourceRecord == null
3558 || curTop.task == sourceRecord.task;
3559 if (callerAtFront) {
3560 // We really do want to push this one into the
3561 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003562 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003563 }
3564 }
3565 // If the caller has requested that the target task be
3566 // reset, then do so.
3567 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3568 taskTop = resetTaskIfNeededLocked(taskTop, r);
3569 }
3570 if (onlyIfNeeded) {
3571 // We don't need to start a new activity, and
3572 // the client said not to do anything if that
3573 // is the case, so this is it! And for paranoia, make
3574 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003575 if (doResume) {
3576 resumeTopActivityLocked(null);
3577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 return START_RETURN_INTENT_TO_CALLER;
3579 }
3580 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3581 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3582 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3583 // In this situation we want to remove all activities
3584 // from the task up to the one being started. In most
3585 // cases this means we are resetting the task to its
3586 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003587 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003588 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 if (top != null) {
3590 if (top.frontOfTask) {
3591 // Activity aliases may mean we use different
3592 // intents for the top activity, so make sure
3593 // the task now has the identity of the new
3594 // intent.
3595 top.task.setIntent(r.intent, r.info);
3596 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003597 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003598 deliverNewIntentLocked(top, r.intent);
3599 } else {
3600 // A special case: we need to
3601 // start the activity because it is not currently
3602 // running, and the caller has asked to clear the
3603 // current task to have this activity at the top.
3604 addingToTask = true;
3605 // Now pretend like this activity is being started
3606 // by the top of its task, so it is put in the
3607 // right place.
3608 sourceRecord = taskTop;
3609 }
3610 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3611 // In this case the top activity on the task is the
3612 // same as the one being launched, so we take that
3613 // as a request to bring the task to the foreground.
3614 // If the top activity in the task is the root
3615 // activity, deliver this new intent to it if it
3616 // desires.
3617 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3618 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003619 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 if (taskTop.frontOfTask) {
3621 taskTop.task.setIntent(r.intent, r.info);
3622 }
3623 deliverNewIntentLocked(taskTop, r.intent);
3624 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3625 // In this case we are launching the root activity
3626 // of the task, but with a different intent. We
3627 // should start a new instance on top.
3628 addingToTask = true;
3629 sourceRecord = taskTop;
3630 }
3631 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3632 // In this case an activity is being launched in to an
3633 // existing task, without resetting that task. This
3634 // is typically the situation of launching an activity
3635 // from a notification or shortcut. We want to place
3636 // the new activity on top of the current task.
3637 addingToTask = true;
3638 sourceRecord = taskTop;
3639 } else if (!taskTop.task.rootWasReset) {
3640 // In this case we are launching in to an existing task
3641 // that has not yet been started from its front door.
3642 // The current task has been brought to the front.
3643 // Ideally, we'd probably like to place this new task
3644 // at the bottom of its stack, but that's a little hard
3645 // to do with the current organization of the code so
3646 // for now we'll just drop it.
3647 taskTop.task.setIntent(r.intent, r.info);
3648 }
3649 if (!addingToTask) {
3650 // We didn't do anything... but it was needed (a.k.a., client
3651 // don't use that intent!) And for paranoia, make
3652 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003653 if (doResume) {
3654 resumeTopActivityLocked(null);
3655 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003656 return START_TASK_TO_FRONT;
3657 }
3658 }
3659 }
3660 }
3661
3662 //String uri = r.intent.toURI();
3663 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003664 //Slog.i(TAG, "Given intent: " + r.intent);
3665 //Slog.i(TAG, "URI is: " + uri);
3666 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667
3668 if (r.packageName != null) {
3669 // If the activity being launched is the same as the one currently
3670 // at the top, then we need to check if it should only be launched
3671 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003672 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3673 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 if (top.realActivity.equals(r.realActivity)) {
3675 if (top.app != null && top.app.thread != null) {
3676 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3677 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3678 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003679 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 // For paranoia, make sure we have correctly
3681 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003682 if (doResume) {
3683 resumeTopActivityLocked(null);
3684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 if (onlyIfNeeded) {
3686 // We don't need to start a new activity, and
3687 // the client said not to do anything if that
3688 // is the case, so this is it!
3689 return START_RETURN_INTENT_TO_CALLER;
3690 }
3691 deliverNewIntentLocked(top, r.intent);
3692 return START_DELIVERED_TO_TOP;
3693 }
3694 }
3695 }
3696 }
3697
3698 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003699 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003700 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003701 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003702 Activity.RESULT_CANCELED, null);
3703 }
3704 return START_CLASS_NOT_FOUND;
3705 }
3706
3707 boolean newTask = false;
3708
3709 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003710 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003711 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3712 // todo: should do better management of integers.
3713 mCurTask++;
3714 if (mCurTask <= 0) {
3715 mCurTask = 1;
3716 }
3717 r.task = new TaskRecord(mCurTask, r.info, intent,
3718 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003719 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720 + " in new task " + r.task);
3721 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003722 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003723
3724 } else if (sourceRecord != null) {
3725 if (!addingToTask &&
3726 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3727 // In this case, we are adding the activity to an existing
3728 // task, but the caller has asked to clear that task if the
3729 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003730 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003731 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003732 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003733 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003734 deliverNewIntentLocked(top, r.intent);
3735 // For paranoia, make sure we have correctly
3736 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003737 if (doResume) {
3738 resumeTopActivityLocked(null);
3739 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 return START_DELIVERED_TO_TOP;
3741 }
3742 } else if (!addingToTask &&
3743 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3744 // In this case, we are launching an activity in our own task
3745 // that may already be running somewhere in the history, and
3746 // we want to shuffle it to the front of the stack if so.
3747 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3748 if (where >= 0) {
3749 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003750 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003752 if (doResume) {
3753 resumeTopActivityLocked(null);
3754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755 return START_DELIVERED_TO_TOP;
3756 }
3757 }
3758 // An existing activity is starting this new activity, so we want
3759 // to keep the new one in the same task as the one that is starting
3760 // it.
3761 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003762 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 + " in existing task " + r.task);
3764
3765 } else {
3766 // This not being started from an existing activity, and not part
3767 // of a new task... just put it in the top task, though these days
3768 // this case should never happen.
3769 final int N = mHistory.size();
3770 HistoryRecord prev =
3771 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3772 r.task = prev != null
3773 ? prev.task
3774 : new TaskRecord(mCurTask, r.info, intent,
3775 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003776 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003777 + " in new guessed " + r.task);
3778 }
3779 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003780 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003781 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003782 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003783 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784 return START_SUCCESS;
3785 }
3786
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003787 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3788 long thisTime, long totalTime) {
3789 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3790 WaitResult w = mWaitingActivityLaunched.get(i);
3791 w.timeout = timeout;
3792 if (r != null) {
3793 w.who = new ComponentName(r.info.packageName, r.info.name);
3794 }
3795 w.thisTime = thisTime;
3796 w.totalTime = totalTime;
3797 }
3798 notify();
3799 }
3800
3801 void reportActivityVisibleLocked(HistoryRecord r) {
3802 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3803 WaitResult w = mWaitingActivityVisible.get(i);
3804 w.timeout = false;
3805 if (r != null) {
3806 w.who = new ComponentName(r.info.packageName, r.info.name);
3807 }
3808 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3809 w.thisTime = w.totalTime;
3810 }
3811 notify();
3812 }
3813
3814 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003815 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3816 int grantedMode, IBinder resultTo,
3817 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003818 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 // Refuse possible leaked file descriptors
3820 if (intent != null && intent.hasFileDescriptors()) {
3821 throw new IllegalArgumentException("File descriptors passed in Intent");
3822 }
3823
Dianne Hackborn860755f2010-06-03 18:47:52 -07003824 boolean componentSpecified = intent.getComponent() != null;
The Android Open Source Project4df24232009-03-05 14:34:35 -08003825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 // Don't modify the client's object!
3827 intent = new Intent(intent);
3828
3829 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 ActivityInfo aInfo;
3831 try {
3832 ResolveInfo rInfo =
3833 ActivityThread.getPackageManager().resolveIntent(
3834 intent, resolvedType,
3835 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003836 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003837 aInfo = rInfo != null ? rInfo.activityInfo : null;
3838 } catch (RemoteException e) {
3839 aInfo = null;
3840 }
3841
3842 if (aInfo != null) {
3843 // Store the found target back into the intent, because now that
3844 // we have it we never want to do this again. For example, if the
3845 // user navigates back to this point in the history, we should
3846 // always restart the exact same activity.
3847 intent.setComponent(new ComponentName(
3848 aInfo.applicationInfo.packageName, aInfo.name));
3849
3850 // Don't debug things in the system process
3851 if (debug) {
3852 if (!aInfo.processName.equals("system")) {
3853 setDebugApp(aInfo.processName, true, false);
3854 }
3855 }
3856 }
3857
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003858 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003859 int callingPid;
3860 int callingUid;
3861 if (caller == null) {
3862 callingPid = Binder.getCallingPid();
3863 callingUid = Binder.getCallingUid();
3864 } else {
3865 callingPid = callingUid = -1;
3866 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003867
3868 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003869 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3870 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003873
Dianne Hackborn860755f2010-06-03 18:47:52 -07003874 if (aInfo != null &&
3875 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
3876 // This may be a heavy-weight process! Check to see if we already
3877 // have another, different heavy-weight process running.
3878 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
3879 if (mHeavyWeightProcess != null &&
3880 (mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
3881 !mHeavyWeightProcess.processName.equals(aInfo.processName))) {
3882 int realCallingPid = callingPid;
3883 int realCallingUid = callingUid;
3884 if (caller != null) {
3885 ProcessRecord callerApp = getRecordForAppLocked(caller);
3886 if (callerApp != null) {
3887 realCallingPid = callerApp.pid;
3888 realCallingUid = callerApp.info.uid;
3889 } else {
3890 Slog.w(TAG, "Unable to find app for caller " + caller
3891 + " (pid=" + realCallingPid + ") when starting: "
3892 + intent.toString());
3893 return START_PERMISSION_DENIED;
3894 }
3895 }
3896
3897 IIntentSender target = getIntentSenderLocked(
3898 IActivityManager.INTENT_SENDER_ACTIVITY, "android",
3899 realCallingUid, null, null, 0, intent,
3900 resolvedType, PendingIntent.FLAG_CANCEL_CURRENT
3901 | PendingIntent.FLAG_ONE_SHOT);
3902
3903 Intent newIntent = new Intent();
3904 if (requestCode >= 0) {
3905 // Caller is requesting a result.
3906 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3907 }
3908 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
3909 new IntentSender(target));
3910 if (mHeavyWeightProcess.activities.size() > 0) {
3911 HistoryRecord hist = mHeavyWeightProcess.activities.get(0);
3912 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
3913 hist.packageName);
3914 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3915 hist.task.taskId);
3916 }
3917 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3918 aInfo.packageName);
3919 newIntent.setFlags(intent.getFlags());
3920 newIntent.setClassName("android",
3921 HeavyWeightSwitcherActivity.class.getName());
3922 intent = newIntent;
3923 resolvedType = null;
3924 caller = null;
3925 callingUid = Binder.getCallingUid();
3926 callingPid = Binder.getCallingPid();
3927 componentSpecified = true;
3928 try {
3929 ResolveInfo rInfo =
3930 ActivityThread.getPackageManager().resolveIntent(
3931 intent, null,
3932 PackageManager.MATCH_DEFAULT_ONLY
3933 | STOCK_PM_FLAGS);
3934 aInfo = rInfo != null ? rInfo.activityInfo : null;
3935 } catch (RemoteException e) {
3936 aInfo = null;
3937 }
3938 }
3939 }
3940 }
3941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 int res = startActivityLocked(caller, intent, resolvedType,
3943 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003944 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003945 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003946
Dianne Hackborne2522462010-03-29 18:41:30 -07003947 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003948 // If the caller also wants to switch to a new configuration,
3949 // do so now. This allows a clean switch, as we are waiting
3950 // for the current activity to pause (so we will not destroy
3951 // it), and have not yet started the next activity.
3952 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3953 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003954 mConfigWillChange = false;
3955 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3956 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003957 updateConfigurationLocked(config, null);
3958 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003961
3962 if (outResult != null) {
3963 outResult.result = res;
3964 if (res == IActivityManager.START_SUCCESS) {
3965 mWaitingActivityLaunched.add(outResult);
3966 do {
3967 try {
3968 wait();
3969 } catch (InterruptedException e) {
3970 }
3971 } while (!outResult.timeout && outResult.who == null);
3972 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3973 HistoryRecord r = this.topRunningActivityLocked(null);
3974 if (r.nowVisible) {
3975 outResult.timeout = false;
3976 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3977 outResult.totalTime = 0;
3978 outResult.thisTime = 0;
3979 } else {
3980 outResult.thisTime = SystemClock.uptimeMillis();
3981 mWaitingActivityVisible.add(outResult);
3982 do {
3983 try {
3984 wait();
3985 } catch (InterruptedException e) {
3986 }
3987 } while (!outResult.timeout && outResult.who == null);
3988 }
3989 }
3990 }
3991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003992 return res;
3993 }
3994 }
3995
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003996 public final int startActivity(IApplicationThread caller,
3997 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3998 int grantedMode, IBinder resultTo,
3999 String resultWho, int requestCode, boolean onlyIfNeeded,
4000 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07004001 return startActivityMayWait(caller, intent, resolvedType,
4002 grantedUriPermissions, grantedMode, resultTo, resultWho,
4003 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08004004 }
4005
4006 public final WaitResult startActivityAndWait(IApplicationThread caller,
4007 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
4008 int grantedMode, IBinder resultTo,
4009 String resultWho, int requestCode, boolean onlyIfNeeded,
4010 boolean debug) {
4011 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07004012 startActivityMayWait(caller, intent, resolvedType,
4013 grantedUriPermissions, grantedMode, resultTo, resultWho,
4014 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08004015 return res;
4016 }
4017
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07004018 public final int startActivityWithConfig(IApplicationThread caller,
4019 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
4020 int grantedMode, IBinder resultTo,
4021 String resultWho, int requestCode, boolean onlyIfNeeded,
4022 boolean debug, Configuration config) {
4023 return startActivityMayWait(caller, intent, resolvedType,
4024 grantedUriPermissions, grantedMode, resultTo, resultWho,
4025 requestCode, onlyIfNeeded, debug, null, config);
4026 }
4027
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08004028 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07004029 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07004030 IBinder resultTo, String resultWho, int requestCode,
4031 int flagsMask, int flagsValues) {
4032 // Refuse possible leaked file descriptors
4033 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
4034 throw new IllegalArgumentException("File descriptors passed in Intent");
4035 }
4036
4037 IIntentSender sender = intent.getTarget();
4038 if (!(sender instanceof PendingIntentRecord)) {
4039 throw new IllegalArgumentException("Bad PendingIntent object");
4040 }
4041
4042 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07004043
4044 synchronized (this) {
4045 // If this is coming from the currently resumed activity, it is
4046 // effectively saying that app switches are allowed at this point.
4047 if (mResumedActivity != null
4048 && mResumedActivity.info.applicationInfo.uid ==
4049 Binder.getCallingUid()) {
4050 mAppSwitchesAllowedTime = 0;
4051 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07004052 }
4053
4054 return pir.sendInner(0, fillInIntent, resolvedType,
4055 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
4056 }
4057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004058 public boolean startNextMatchingActivity(IBinder callingActivity,
4059 Intent intent) {
4060 // Refuse possible leaked file descriptors
4061 if (intent != null && intent.hasFileDescriptors() == true) {
4062 throw new IllegalArgumentException("File descriptors passed in Intent");
4063 }
4064
4065 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004066 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004067 if (index < 0) {
4068 return false;
4069 }
4070 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4071 if (r.app == null || r.app.thread == null) {
4072 // The caller is not running... d'oh!
4073 return false;
4074 }
4075 intent = new Intent(intent);
4076 // The caller is not allowed to change the data.
4077 intent.setDataAndType(r.intent.getData(), r.intent.getType());
4078 // And we are resetting to find the next component...
4079 intent.setComponent(null);
4080
4081 ActivityInfo aInfo = null;
4082 try {
4083 List<ResolveInfo> resolves =
4084 ActivityThread.getPackageManager().queryIntentActivities(
4085 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004086 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004087
4088 // Look for the original activity in the list...
4089 final int N = resolves != null ? resolves.size() : 0;
4090 for (int i=0; i<N; i++) {
4091 ResolveInfo rInfo = resolves.get(i);
4092 if (rInfo.activityInfo.packageName.equals(r.packageName)
4093 && rInfo.activityInfo.name.equals(r.info.name)) {
4094 // We found the current one... the next matching is
4095 // after it.
4096 i++;
4097 if (i<N) {
4098 aInfo = resolves.get(i).activityInfo;
4099 }
4100 break;
4101 }
4102 }
4103 } catch (RemoteException e) {
4104 }
4105
4106 if (aInfo == null) {
4107 // Nobody who is next!
4108 return false;
4109 }
4110
4111 intent.setComponent(new ComponentName(
4112 aInfo.applicationInfo.packageName, aInfo.name));
4113 intent.setFlags(intent.getFlags()&~(
4114 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
4115 Intent.FLAG_ACTIVITY_CLEAR_TOP|
4116 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
4117 Intent.FLAG_ACTIVITY_NEW_TASK));
4118
4119 // Okay now we need to start the new activity, replacing the
4120 // currently running activity. This is a little tricky because
4121 // we want to start the new one as if the current one is finished,
4122 // but not finish the current one first so that there is no flicker.
4123 // And thus...
4124 final boolean wasFinishing = r.finishing;
4125 r.finishing = true;
4126
4127 // Propagate reply information over to the new activity.
4128 final HistoryRecord resultTo = r.resultTo;
4129 final String resultWho = r.resultWho;
4130 final int requestCode = r.requestCode;
4131 r.resultTo = null;
4132 if (resultTo != null) {
4133 resultTo.removeResultsLocked(r, resultWho, requestCode);
4134 }
4135
4136 final long origId = Binder.clearCallingIdentity();
4137 // XXX we are not dealing with propagating grantedUriPermissions...
4138 // those are not yet exposed to user code, so there is no need.
4139 int res = startActivityLocked(r.app.thread, intent,
4140 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004141 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004142 Binder.restoreCallingIdentity(origId);
4143
4144 r.finishing = wasFinishing;
4145 if (res != START_SUCCESS) {
4146 return false;
4147 }
4148 return true;
4149 }
4150 }
4151
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004152 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004153 Intent intent, String resolvedType, IBinder resultTo,
4154 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004155
4156 // This is so super not safe, that only the system (or okay root)
4157 // can do it.
4158 final int callingUid = Binder.getCallingUid();
4159 if (callingUid != 0 && callingUid != Process.myUid()) {
4160 throw new SecurityException(
4161 "startActivityInPackage only available to the system");
4162 }
4163
The Android Open Source Project4df24232009-03-05 14:34:35 -08004164 final boolean componentSpecified = intent.getComponent() != null;
4165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 // Don't modify the client's object!
4167 intent = new Intent(intent);
4168
4169 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 ActivityInfo aInfo;
4171 try {
4172 ResolveInfo rInfo =
4173 ActivityThread.getPackageManager().resolveIntent(
4174 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004175 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004176 aInfo = rInfo != null ? rInfo.activityInfo : null;
4177 } catch (RemoteException e) {
4178 aInfo = null;
4179 }
4180
4181 if (aInfo != null) {
4182 // Store the found target back into the intent, because now that
4183 // we have it we never want to do this again. For example, if the
4184 // user navigates back to this point in the history, we should
4185 // always restart the exact same activity.
4186 intent.setComponent(new ComponentName(
4187 aInfo.applicationInfo.packageName, aInfo.name));
4188 }
4189
4190 synchronized(this) {
4191 return startActivityLocked(null, intent, resolvedType,
4192 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004193 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 }
4195 }
4196
Josh Bartel7f208742010-02-25 11:01:44 -06004197 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004198 // Remove any existing entries that are the same kind of task.
4199 int N = mRecentTasks.size();
4200 for (int i=0; i<N; i++) {
4201 TaskRecord tr = mRecentTasks.get(i);
4202 if ((task.affinity != null && task.affinity.equals(tr.affinity))
4203 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
4204 mRecentTasks.remove(i);
4205 i--;
4206 N--;
4207 if (task.intent == null) {
4208 // If the new recent task we are adding is not fully
4209 // specified, then replace it with the existing recent task.
4210 task = tr;
4211 }
4212 }
4213 }
4214 if (N >= MAX_RECENT_TASKS) {
4215 mRecentTasks.remove(N-1);
4216 }
4217 mRecentTasks.add(0, task);
4218 }
4219
4220 public void setRequestedOrientation(IBinder token,
4221 int requestedOrientation) {
4222 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004223 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 if (index < 0) {
4225 return;
4226 }
4227 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4228 final long origId = Binder.clearCallingIdentity();
4229 mWindowManager.setAppOrientation(r, requestedOrientation);
4230 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07004231 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232 r.mayFreezeScreenLocked(r.app) ? r : null);
4233 if (config != null) {
4234 r.frozenBeforeDestroy = true;
4235 if (!updateConfigurationLocked(config, r)) {
4236 resumeTopActivityLocked(null);
4237 }
4238 }
4239 Binder.restoreCallingIdentity(origId);
4240 }
4241 }
4242
4243 public int getRequestedOrientation(IBinder token) {
4244 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004245 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004246 if (index < 0) {
4247 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
4248 }
4249 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4250 return mWindowManager.getAppOrientation(r);
4251 }
4252 }
4253
4254 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004255 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004256 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4257 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
4258 if (!r.finishing) {
4259 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
4260 "no-history");
4261 }
4262 } else if (r.app != null && r.app.thread != null) {
4263 if (mFocusedActivity == r) {
4264 setFocusedActivityLocked(topRunningActivityLocked(null));
4265 }
4266 r.resumeKeyDispatchingLocked();
4267 try {
4268 r.stopped = false;
4269 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004270 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004271 TAG, "Stopping visible=" + r.visible + " for " + r);
4272 if (!r.visible) {
4273 mWindowManager.setAppVisibility(r, false);
4274 }
4275 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4276 } catch (Exception e) {
4277 // Maybe just ignore exceptions here... if the process
4278 // has crashed, our death notification will clean things
4279 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004280 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 // Just in case, assume it to be stopped.
4282 r.stopped = true;
4283 r.state = ActivityState.STOPPED;
4284 if (r.configDestroy) {
4285 destroyActivityLocked(r, true);
4286 }
4287 }
4288 }
4289 }
4290
4291 /**
4292 * @return Returns true if the activity is being finished, false if for
4293 * some reason it is being left as-is.
4294 */
4295 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4296 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004297 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 TAG, "Finishing activity: token=" + token
4299 + ", result=" + resultCode + ", data=" + resultData);
4300
Dianne Hackborn75b03852009-06-12 15:43:26 -07004301 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 if (index < 0) {
4303 return false;
4304 }
4305 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4306
4307 // Is this the last activity left?
4308 boolean lastActivity = true;
4309 for (int i=mHistory.size()-1; i>=0; i--) {
4310 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4311 if (!p.finishing && p != r) {
4312 lastActivity = false;
4313 break;
4314 }
4315 }
4316
4317 // If this is the last activity, but it is the home activity, then
4318 // just don't finish it.
4319 if (lastActivity) {
4320 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4321 return false;
4322 }
4323 }
4324
4325 finishActivityLocked(r, index, resultCode, resultData, reason);
4326 return true;
4327 }
4328
4329 /**
4330 * @return Returns true if this activity has been removed from the history
4331 * list, or false if it is still in the list and will be removed later.
4332 */
4333 private final boolean finishActivityLocked(HistoryRecord r, int index,
4334 int resultCode, Intent resultData, String reason) {
4335 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004336 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004337 return false;
4338 }
4339
4340 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004341 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004342 System.identityHashCode(r),
4343 r.task.taskId, r.shortComponentName, reason);
4344 r.task.numActivities--;
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004345 if (index < (mHistory.size()-1)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4347 if (next.task == r.task) {
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004348 if (r.frontOfTask) {
4349 // The next activity is now the front of the task.
4350 next.frontOfTask = true;
4351 }
4352 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4353 // If the caller asked that this activity (and all above it)
4354 // be cleared when the task is reset, don't lose that information,
4355 // but propagate it up to the next activity.
4356 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358 }
4359 }
4360
4361 r.pauseKeyDispatchingLocked();
4362 if (mFocusedActivity == r) {
4363 setFocusedActivityLocked(topRunningActivityLocked(null));
4364 }
4365
4366 // send the result
4367 HistoryRecord resultTo = r.resultTo;
4368 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004369 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004370 + " who=" + r.resultWho + " req=" + r.requestCode
4371 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372 if (r.info.applicationInfo.uid > 0) {
4373 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4374 r.packageName, resultData, r);
4375 }
4376 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4377 resultData);
4378 r.resultTo = null;
4379 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004380 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004381
4382 // Make sure this HistoryRecord is not holding on to other resources,
4383 // because clients have remote IPC references to this object so we
4384 // can't assume that will go away and want to avoid circular IPC refs.
4385 r.results = null;
4386 r.pendingResults = null;
4387 r.newIntents = null;
4388 r.icicle = null;
4389
4390 if (mPendingThumbnails.size() > 0) {
4391 // There are clients waiting to receive thumbnails so, in case
4392 // this is an activity that someone is waiting for, add it
4393 // to the pending list so we can correctly update the clients.
4394 mCancelledThumbnails.add(r);
4395 }
4396
4397 if (mResumedActivity == r) {
4398 boolean endTask = index <= 0
4399 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004400 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004401 "Prepare close transition: finishing " + r);
4402 mWindowManager.prepareAppTransition(endTask
4403 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4404 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4405
4406 // Tell window manager to prepare for this one to be removed.
4407 mWindowManager.setAppVisibility(r, false);
4408
4409 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004410 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4411 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 startPausingLocked(false, false);
4413 }
4414
4415 } else if (r.state != ActivityState.PAUSING) {
4416 // If the activity is PAUSING, we will complete the finish once
4417 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004418 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004419 return finishCurrentActivityLocked(r, index,
4420 FINISH_AFTER_PAUSE) == null;
4421 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004422 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 }
4424
4425 return false;
4426 }
4427
4428 private static final int FINISH_IMMEDIATELY = 0;
4429 private static final int FINISH_AFTER_PAUSE = 1;
4430 private static final int FINISH_AFTER_VISIBLE = 2;
4431
4432 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4433 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004434 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 if (index < 0) {
4436 return null;
4437 }
4438
4439 return finishCurrentActivityLocked(r, index, mode);
4440 }
4441
4442 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4443 int index, int mode) {
4444 // First things first: if this activity is currently visible,
4445 // and the resumed activity is not yet visible, then hold off on
4446 // finishing until the resumed one becomes visible.
4447 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4448 if (!mStoppingActivities.contains(r)) {
4449 mStoppingActivities.add(r);
4450 if (mStoppingActivities.size() > 3) {
4451 // If we already have a few activities waiting to stop,
4452 // then give up on things going idle and start clearing
4453 // them out.
4454 Message msg = Message.obtain();
4455 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4456 mHandler.sendMessage(msg);
4457 }
4458 }
4459 r.state = ActivityState.STOPPING;
4460 updateOomAdjLocked();
4461 return r;
4462 }
4463
4464 // make sure the record is cleaned out of other places.
4465 mStoppingActivities.remove(r);
4466 mWaitingVisibleActivities.remove(r);
4467 if (mResumedActivity == r) {
4468 mResumedActivity = null;
4469 }
4470 final ActivityState prevState = r.state;
4471 r.state = ActivityState.FINISHING;
4472
4473 if (mode == FINISH_IMMEDIATELY
4474 || prevState == ActivityState.STOPPED
4475 || prevState == ActivityState.INITIALIZING) {
4476 // If this activity is already stopped, we can just finish
4477 // it right now.
4478 return destroyActivityLocked(r, true) ? null : r;
4479 } else {
4480 // Need to go through the full pause cycle to get this
4481 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004482 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004483 mFinishingActivities.add(r);
4484 resumeTopActivityLocked(null);
4485 }
4486 return r;
4487 }
4488
4489 /**
4490 * This is the internal entry point for handling Activity.finish().
4491 *
4492 * @param token The Binder token referencing the Activity we want to finish.
4493 * @param resultCode Result code, if any, from this Activity.
4494 * @param resultData Result data (Intent), if any, from this Activity.
4495 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004496 * @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 -08004497 */
4498 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4499 // Refuse possible leaked file descriptors
4500 if (resultData != null && resultData.hasFileDescriptors() == true) {
4501 throw new IllegalArgumentException("File descriptors passed in Intent");
4502 }
4503
4504 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004505 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 // Find the first activity that is not finishing.
4507 HistoryRecord next = topRunningActivityLocked(token, 0);
4508 if (next != null) {
4509 // ask watcher if this is allowed
4510 boolean resumeOK = true;
4511 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004512 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004514 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004515 }
4516
4517 if (!resumeOK) {
4518 return false;
4519 }
4520 }
4521 }
4522 final long origId = Binder.clearCallingIdentity();
4523 boolean res = requestFinishActivityLocked(token, resultCode,
4524 resultData, "app-request");
4525 Binder.restoreCallingIdentity(origId);
4526 return res;
4527 }
4528 }
4529
Dianne Hackborn860755f2010-06-03 18:47:52 -07004530 public final void finishHeavyWeightApp() {
4531 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4532 != PackageManager.PERMISSION_GRANTED) {
4533 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
4534 + Binder.getCallingPid()
4535 + ", uid=" + Binder.getCallingUid()
4536 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4537 Slog.w(TAG, msg);
4538 throw new SecurityException(msg);
4539 }
4540
4541 synchronized(this) {
4542 if (mHeavyWeightProcess == null) {
4543 return;
4544 }
4545
4546 ArrayList<HistoryRecord> activities = new ArrayList<HistoryRecord>(
4547 mHeavyWeightProcess.activities);
4548 for (int i=0; i<activities.size(); i++) {
4549 HistoryRecord r = activities.get(i);
4550 if (!r.finishing) {
4551 int index = indexOfTokenLocked(r);
4552 if (index >= 0) {
4553 finishActivityLocked(r, index, Activity.RESULT_CANCELED,
4554 null, "finish-heavy");
4555 }
4556 }
4557 }
4558
4559 mHeavyWeightProcess = null;
4560 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4561 }
4562 }
4563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004564 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4565 String resultWho, int requestCode, int resultCode, Intent data) {
4566
4567 if (callingUid > 0) {
4568 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4569 data, r);
4570 }
4571
Joe Onorato8a9b2202010-02-26 18:56:32 -08004572 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004573 + " : who=" + resultWho + " req=" + requestCode
4574 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4576 try {
4577 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4578 list.add(new ResultInfo(resultWho, requestCode,
4579 resultCode, data));
4580 r.app.thread.scheduleSendResult(r, list);
4581 return;
4582 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004583 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004584 }
4585 }
4586
4587 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4588 }
4589
4590 public final void finishSubActivity(IBinder token, String resultWho,
4591 int requestCode) {
4592 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004593 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 if (index < 0) {
4595 return;
4596 }
4597 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4598
4599 final long origId = Binder.clearCallingIdentity();
4600
4601 int i;
4602 for (i=mHistory.size()-1; i>=0; i--) {
4603 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4604 if (r.resultTo == self && r.requestCode == requestCode) {
4605 if ((r.resultWho == null && resultWho == null) ||
4606 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4607 finishActivityLocked(r, i,
4608 Activity.RESULT_CANCELED, null, "request-sub");
4609 }
4610 }
4611 }
4612
4613 Binder.restoreCallingIdentity(origId);
4614 }
4615 }
4616
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004617 public boolean willActivityBeVisible(IBinder token) {
4618 synchronized(this) {
4619 int i;
4620 for (i=mHistory.size()-1; i>=0; i--) {
4621 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4622 if (r == token) {
4623 return true;
4624 }
4625 if (r.fullscreen && !r.finishing) {
4626 return false;
4627 }
4628 }
4629 return true;
4630 }
4631 }
4632
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004633 public void overridePendingTransition(IBinder token, String packageName,
4634 int enterAnim, int exitAnim) {
4635 synchronized(this) {
4636 int index = indexOfTokenLocked(token);
4637 if (index < 0) {
4638 return;
4639 }
4640 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4641
4642 final long origId = Binder.clearCallingIdentity();
4643
4644 if (self.state == ActivityState.RESUMED
4645 || self.state == ActivityState.PAUSING) {
4646 mWindowManager.overridePendingAppTransition(packageName,
4647 enterAnim, exitAnim);
4648 }
4649
4650 Binder.restoreCallingIdentity(origId);
4651 }
4652 }
4653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004654 /**
4655 * Perform clean-up of service connections in an activity record.
4656 */
4657 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4658 // Throw away any services that have been bound by this activity.
4659 if (r.connections != null) {
4660 Iterator<ConnectionRecord> it = r.connections.iterator();
4661 while (it.hasNext()) {
4662 ConnectionRecord c = it.next();
4663 removeConnectionLocked(c, null, r);
4664 }
4665 r.connections = null;
4666 }
4667 }
4668
4669 /**
4670 * Perform the common clean-up of an activity record. This is called both
4671 * as part of destroyActivityLocked() (when destroying the client-side
4672 * representation) and cleaning things up as a result of its hosting
4673 * processing going away, in which case there is no remaining client-side
4674 * state to destroy so only the cleanup here is needed.
4675 */
4676 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4677 if (mResumedActivity == r) {
4678 mResumedActivity = null;
4679 }
4680 if (mFocusedActivity == r) {
4681 mFocusedActivity = null;
4682 }
4683
4684 r.configDestroy = false;
4685 r.frozenBeforeDestroy = false;
4686
4687 // Make sure this record is no longer in the pending finishes list.
4688 // This could happen, for example, if we are trimming activities
4689 // down to the max limit while they are still waiting to finish.
4690 mFinishingActivities.remove(r);
4691 mWaitingVisibleActivities.remove(r);
4692
4693 // Remove any pending results.
4694 if (r.finishing && r.pendingResults != null) {
4695 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4696 PendingIntentRecord rec = apr.get();
4697 if (rec != null) {
4698 cancelIntentSenderLocked(rec, false);
4699 }
4700 }
4701 r.pendingResults = null;
4702 }
4703
4704 if (cleanServices) {
4705 cleanUpActivityServicesLocked(r);
4706 }
4707
4708 if (mPendingThumbnails.size() > 0) {
4709 // There are clients waiting to receive thumbnails so, in case
4710 // this is an activity that someone is waiting for, add it
4711 // to the pending list so we can correctly update the clients.
4712 mCancelledThumbnails.add(r);
4713 }
4714
4715 // Get rid of any pending idle timeouts.
4716 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4717 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4718 }
4719
4720 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4721 if (r.state != ActivityState.DESTROYED) {
4722 mHistory.remove(r);
4723 r.inHistory = false;
4724 r.state = ActivityState.DESTROYED;
4725 mWindowManager.removeAppToken(r);
4726 if (VALIDATE_TOKENS) {
4727 mWindowManager.validateAppTokens(mHistory);
4728 }
4729 cleanUpActivityServicesLocked(r);
4730 removeActivityUriPermissionsLocked(r);
4731 }
4732 }
4733
4734 /**
4735 * Destroy the current CLIENT SIDE instance of an activity. This may be
4736 * called both when actually finishing an activity, or when performing
4737 * a configuration switch where we destroy the current client-side object
4738 * but then create a new client-side object for this same HistoryRecord.
4739 */
4740 private final boolean destroyActivityLocked(HistoryRecord r,
4741 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004742 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004743 TAG, "Removing activity: token=" + r
4744 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004745 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 System.identityHashCode(r),
4747 r.task.taskId, r.shortComponentName);
4748
4749 boolean removedFromHistory = false;
4750
4751 cleanUpActivityLocked(r, false);
4752
Dianne Hackborn03abb812010-01-04 18:43:19 -08004753 final boolean hadApp = r.app != null;
4754
4755 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 if (removeFromApp) {
4757 int idx = r.app.activities.indexOf(r);
4758 if (idx >= 0) {
4759 r.app.activities.remove(idx);
4760 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004761 if (mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4762 mHeavyWeightProcess = null;
4763 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004765 if (r.persistent) {
4766 decPersistentCountLocked(r.app);
4767 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004768 if (r.app.activities.size() == 0) {
4769 // No longer have activities, so update location in
4770 // LRU list.
4771 updateLruProcessLocked(r.app, true, false);
4772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 }
4774
4775 boolean skipDestroy = false;
4776
4777 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004778 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004779 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4780 r.configChangeFlags);
4781 } catch (Exception e) {
4782 // We can just ignore exceptions here... if the process
4783 // has crashed, our death notification will clean things
4784 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004785 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004786 if (r.finishing) {
4787 removeActivityFromHistoryLocked(r);
4788 removedFromHistory = true;
4789 skipDestroy = true;
4790 }
4791 }
4792
4793 r.app = null;
4794 r.nowVisible = false;
4795
4796 if (r.finishing && !skipDestroy) {
4797 r.state = ActivityState.DESTROYING;
4798 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4799 msg.obj = r;
4800 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4801 } else {
4802 r.state = ActivityState.DESTROYED;
4803 }
4804 } else {
4805 // remove this record from the history.
4806 if (r.finishing) {
4807 removeActivityFromHistoryLocked(r);
4808 removedFromHistory = true;
4809 } else {
4810 r.state = ActivityState.DESTROYED;
4811 }
4812 }
4813
4814 r.configChangeFlags = 0;
4815
Dianne Hackborn03abb812010-01-04 18:43:19 -08004816 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004817 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004818 }
4819
4820 return removedFromHistory;
4821 }
4822
Dianne Hackborn03abb812010-01-04 18:43:19 -08004823 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004824 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004825 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 TAG, "Removing app " + app + " from list " + list
4827 + " with " + i + " entries");
4828 while (i > 0) {
4829 i--;
4830 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004831 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4833 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004834 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 list.remove(i);
4836 }
4837 }
4838 }
4839
4840 /**
4841 * Main function for removing an existing process from the activity manager
4842 * as a result of that process going away. Clears out all connections
4843 * to the process.
4844 */
4845 private final void handleAppDiedLocked(ProcessRecord app,
4846 boolean restarting) {
4847 cleanUpApplicationRecordLocked(app, restarting, -1);
4848 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004849 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004850 }
4851
4852 // Just in case...
4853 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004854 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 mPausingActivity = null;
4856 }
4857 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4858 mLastPausedActivity = null;
4859 }
4860
4861 // Remove this application's activities from active lists.
4862 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4863 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4864 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4865 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4866
4867 boolean atTop = true;
4868 boolean hasVisibleActivities = false;
4869
4870 // Clean out the history list.
4871 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004872 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004873 TAG, "Removing app " + app + " from history with " + i + " entries");
4874 while (i > 0) {
4875 i--;
4876 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004877 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004878 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4879 if (r.app == app) {
4880 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004881 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004882 TAG, "Removing this entry! frozen=" + r.haveState
4883 + " finishing=" + r.finishing);
4884 mHistory.remove(i);
4885
4886 r.inHistory = false;
4887 mWindowManager.removeAppToken(r);
4888 if (VALIDATE_TOKENS) {
4889 mWindowManager.validateAppTokens(mHistory);
4890 }
4891 removeActivityUriPermissionsLocked(r);
4892
4893 } else {
4894 // We have the current state for this activity, so
4895 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004896 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004897 TAG, "Keeping entry, setting app to null");
4898 if (r.visible) {
4899 hasVisibleActivities = true;
4900 }
4901 r.app = null;
4902 r.nowVisible = false;
4903 if (!r.haveState) {
4904 r.icicle = null;
4905 }
4906 }
4907
4908 cleanUpActivityLocked(r, true);
4909 r.state = ActivityState.STOPPED;
4910 }
4911 atTop = false;
4912 }
4913
4914 app.activities.clear();
4915
4916 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004917 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 + " running instrumentation " + app.instrumentationClass);
4919 Bundle info = new Bundle();
4920 info.putString("shortMsg", "Process crashed.");
4921 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4922 }
4923
4924 if (!restarting) {
4925 if (!resumeTopActivityLocked(null)) {
4926 // If there was nothing to resume, and we are not already
4927 // restarting this process, but there is a visible activity that
4928 // is hosted by the process... then make sure all visible
4929 // activities are running, taking care of restarting this
4930 // process.
4931 if (hasVisibleActivities) {
4932 ensureActivitiesVisibleLocked(null, 0);
4933 }
4934 }
4935 }
4936 }
4937
4938 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4939 IBinder threadBinder = thread.asBinder();
4940
4941 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004942 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4943 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4945 return i;
4946 }
4947 }
4948 return -1;
4949 }
4950
4951 private final ProcessRecord getRecordForAppLocked(
4952 IApplicationThread thread) {
4953 if (thread == null) {
4954 return null;
4955 }
4956
4957 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004958 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 }
4960
4961 private final void appDiedLocked(ProcessRecord app, int pid,
4962 IApplicationThread thread) {
4963
4964 mProcDeaths[0]++;
4965
Magnus Edlund7bb25812010-02-24 15:45:06 +01004966 // Clean up already done if the process has been re-started.
4967 if (app.pid == pid && app.thread != null &&
4968 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07004969 if (!app.killedBackground) {
4970 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
4971 + ") has died.");
4972 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08004973 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004974 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004975 TAG, "Dying app: " + app + ", pid: " + pid
4976 + ", thread: " + thread.asBinder());
4977 boolean doLowMem = app.instrumentationClass == null;
4978 handleAppDiedLocked(app, false);
4979
4980 if (doLowMem) {
4981 // If there are no longer any background processes running,
4982 // and the app that died was not running instrumentation,
4983 // then tell everyone we are now low on memory.
4984 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004985 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4986 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004987 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4988 haveBg = true;
4989 break;
4990 }
4991 }
4992
4993 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004994 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004995 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004996 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004997 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4998 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004999 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005000 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
5001 // The low memory report is overriding any current
5002 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005003 // heavy/important/visible/foreground processes first.
5004 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005005 rec.lastRequestedGc = 0;
5006 } else {
5007 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005009 rec.reportLowMemory = true;
5010 rec.lastLowMemory = now;
5011 mProcessesToGc.remove(rec);
5012 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 }
5014 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005015 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 }
5017 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01005018 } else if (app.pid != pid) {
5019 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005020 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01005021 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08005022 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005023 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005024 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 + thread.asBinder());
5026 }
5027 }
5028
Dan Egnor42471dd2010-01-07 17:25:22 -08005029 /**
5030 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07005031 * @param clearTraces causes the dump file to be erased prior to the new
5032 * traces being written, if true; when false, the new traces will be
5033 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08005034 * @param pids of dalvik VM processes to dump stack traces for
5035 * @return file containing stack traces, or null if no dump file is configured
5036 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07005037 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005038 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
5039 if (tracesPath == null || tracesPath.length() == 0) {
5040 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005041 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005042
5043 File tracesFile = new File(tracesPath);
5044 try {
5045 File tracesDir = tracesFile.getParentFile();
5046 if (!tracesDir.exists()) tracesFile.mkdirs();
5047 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
5048
Christopher Tate6ee412d2010-05-28 12:01:56 -07005049 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08005050 tracesFile.createNewFile();
5051 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
5052 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005053 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005054 return null;
5055 }
5056
5057 // Use a FileObserver to detect when traces finish writing.
5058 // The order of traces is considered important to maintain for legibility.
5059 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
5060 public synchronized void onEvent(int event, String path) { notify(); }
5061 };
5062
5063 try {
5064 observer.startWatching();
5065 int num = pids.size();
5066 for (int i = 0; i < num; i++) {
5067 synchronized (observer) {
5068 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
5069 observer.wait(200); // Wait for write-close, give up after 200msec
5070 }
5071 }
5072 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08005073 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005074 } finally {
5075 observer.stopWatching();
5076 }
5077
5078 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 }
5080
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005081 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08005082 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005083 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005084
5085 synchronized (this) {
5086 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
5087 if (mShuttingDown) {
5088 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
5089 return;
5090 } else if (app.notResponding) {
5091 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
5092 return;
5093 } else if (app.crashing) {
5094 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
5095 return;
5096 }
5097
5098 // In case we come through here for the same app before completing
5099 // this one, mark as anring now so we will bail out.
5100 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08005101
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005102 // Log the ANR to the event log.
5103 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
5104 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08005105
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005106 // Dump thread traces as quickly as we can, starting with "interesting" processes.
5107 pids.add(app.pid);
5108
5109 int parentPid = app.pid;
5110 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
5111 if (parentPid != app.pid) pids.add(parentPid);
5112
5113 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08005114
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005115 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
5116 ProcessRecord r = mLruProcesses.get(i);
5117 if (r != null && r.thread != null) {
5118 int pid = r.pid;
5119 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
5120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 }
5122 }
5123
Christopher Tate6ee412d2010-05-28 12:01:56 -07005124 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08005125
5126 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005127 StringBuilder info = mStringBuilder;
5128 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08005129 info.append("ANR in ").append(app.processName);
5130 if (activity != null && activity.shortComponentName != null) {
5131 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07005132 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08005133 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005135 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005136 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005137 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005138 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140
Dan Egnor42471dd2010-01-07 17:25:22 -08005141 String cpuInfo = null;
5142 if (MONITOR_CPU_USAGE) {
5143 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005144 synchronized (mProcessStatsThread) {
5145 cpuInfo = mProcessStats.printCurrentState();
5146 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005147 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005148 }
5149
Joe Onorato8a9b2202010-02-26 18:56:32 -08005150 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08005151 if (tracesFile == null) {
5152 // There is no trace file, so dump (only) the alleged culprit's threads to the log
5153 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
5154 }
5155
5156 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
5157
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005158 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005159 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08005160 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
5161 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005162 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005163 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
5164 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 }
5166 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005167 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 }
5169 }
5170
Dan Egnor42471dd2010-01-07 17:25:22 -08005171 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
5172 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
5173 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005174
5175 synchronized (this) {
5176 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
5177 Process.killProcess(app.pid);
5178 return;
5179 }
5180
5181 // Set the app's notResponding state, and look up the errorReportReceiver
5182 makeAppNotRespondingLocked(app,
5183 activity != null ? activity.shortComponentName : null,
5184 annotation != null ? "ANR " + annotation : "ANR",
5185 info.toString());
5186
5187 // Bring up the infamous App Not Responding dialog
5188 Message msg = Message.obtain();
5189 HashMap map = new HashMap();
5190 msg.what = SHOW_NOT_RESPONDING_MSG;
5191 msg.obj = map;
5192 map.put("app", app);
5193 if (activity != null) {
5194 map.put("activity", activity);
5195 }
5196
5197 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08005198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005199 }
5200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 private final void decPersistentCountLocked(ProcessRecord app)
5202 {
5203 app.persistentActivities--;
5204 if (app.persistentActivities > 0) {
5205 // Still more of 'em...
5206 return;
5207 }
5208 if (app.persistent) {
5209 // Ah, but the application itself is persistent. Whatever!
5210 return;
5211 }
5212
5213 // App is no longer persistent... make sure it and the ones
5214 // following it in the LRU list have the correc oom_adj.
5215 updateOomAdjLocked();
5216 }
5217
5218 public void setPersistent(IBinder token, boolean isPersistent) {
5219 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
5220 != PackageManager.PERMISSION_GRANTED) {
5221 String msg = "Permission Denial: setPersistent() from pid="
5222 + Binder.getCallingPid()
5223 + ", uid=" + Binder.getCallingUid()
5224 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005225 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005226 throw new SecurityException(msg);
5227 }
5228
5229 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005230 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005231 if (index < 0) {
5232 return;
5233 }
5234 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5235 ProcessRecord app = r.app;
5236
Joe Onorato8a9b2202010-02-26 18:56:32 -08005237 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005238 TAG, "Setting persistence " + isPersistent + ": " + r);
5239
5240 if (isPersistent) {
5241 if (r.persistent) {
5242 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005243 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005244 return;
5245 }
5246 r.persistent = true;
5247 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005248 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 if (app.persistentActivities > 1) {
5250 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005251 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005252 return;
5253 }
5254 if (app.persistent) {
5255 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005256 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257 return;
5258 }
5259
5260 // App is now persistent... make sure it and the ones
5261 // following it now have the correct oom_adj.
5262 final long origId = Binder.clearCallingIdentity();
5263 updateOomAdjLocked();
5264 Binder.restoreCallingIdentity(origId);
5265
5266 } else {
5267 if (!r.persistent) {
5268 // Okay okay, I heard you already!
5269 return;
5270 }
5271 r.persistent = false;
5272 final long origId = Binder.clearCallingIdentity();
5273 decPersistentCountLocked(app);
5274 Binder.restoreCallingIdentity(origId);
5275
5276 }
5277 }
5278 }
5279
5280 public boolean clearApplicationUserData(final String packageName,
5281 final IPackageDataObserver observer) {
5282 int uid = Binder.getCallingUid();
5283 int pid = Binder.getCallingPid();
5284 long callingId = Binder.clearCallingIdentity();
5285 try {
5286 IPackageManager pm = ActivityThread.getPackageManager();
5287 int pkgUid = -1;
5288 synchronized(this) {
5289 try {
5290 pkgUid = pm.getPackageUid(packageName);
5291 } catch (RemoteException e) {
5292 }
5293 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005294 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 return false;
5296 }
5297 if (uid == pkgUid || checkComponentPermission(
5298 android.Manifest.permission.CLEAR_APP_USER_DATA,
5299 pid, uid, -1)
5300 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005301 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 } else {
5303 throw new SecurityException(pid+" does not have permission:"+
5304 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5305 "for process:"+packageName);
5306 }
5307 }
5308
5309 try {
5310 //clear application user data
5311 pm.clearApplicationUserData(packageName, observer);
5312 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5313 Uri.fromParts("package", packageName, null));
5314 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005315 synchronized (this) {
5316 broadcastIntentLocked(null, null, intent,
5317 null, null, 0, null, null, null,
5318 false, false, MY_PID, Process.SYSTEM_UID);
5319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 } catch (RemoteException e) {
5321 }
5322 } finally {
5323 Binder.restoreCallingIdentity(callingId);
5324 }
5325 return true;
5326 }
5327
Dianne Hackborn03abb812010-01-04 18:43:19 -08005328 public void killBackgroundProcesses(final String packageName) {
5329 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5330 != PackageManager.PERMISSION_GRANTED &&
5331 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5332 != PackageManager.PERMISSION_GRANTED) {
5333 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005334 + Binder.getCallingPid()
5335 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005336 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005337 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338 throw new SecurityException(msg);
5339 }
5340
5341 long callingId = Binder.clearCallingIdentity();
5342 try {
5343 IPackageManager pm = ActivityThread.getPackageManager();
5344 int pkgUid = -1;
5345 synchronized(this) {
5346 try {
5347 pkgUid = pm.getPackageUid(packageName);
5348 } catch (RemoteException e) {
5349 }
5350 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005351 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005352 return;
5353 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005354 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005355 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005356 }
5357 } finally {
5358 Binder.restoreCallingIdentity(callingId);
5359 }
5360 }
5361
5362 public void forceStopPackage(final String packageName) {
5363 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5364 != PackageManager.PERMISSION_GRANTED) {
5365 String msg = "Permission Denial: forceStopPackage() from pid="
5366 + Binder.getCallingPid()
5367 + ", uid=" + Binder.getCallingUid()
5368 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005369 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005370 throw new SecurityException(msg);
5371 }
5372
5373 long callingId = Binder.clearCallingIdentity();
5374 try {
5375 IPackageManager pm = ActivityThread.getPackageManager();
5376 int pkgUid = -1;
5377 synchronized(this) {
5378 try {
5379 pkgUid = pm.getPackageUid(packageName);
5380 } catch (RemoteException e) {
5381 }
5382 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005383 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005384 return;
5385 }
5386 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005387 }
5388 } finally {
5389 Binder.restoreCallingIdentity(callingId);
5390 }
5391 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005392
5393 /*
5394 * The pkg name and uid have to be specified.
5395 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5396 */
5397 public void killApplicationWithUid(String pkg, int uid) {
5398 if (pkg == null) {
5399 return;
5400 }
5401 // Make sure the uid is valid.
5402 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005403 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005404 return;
5405 }
5406 int callerUid = Binder.getCallingUid();
5407 // Only the system server can kill an application
5408 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005409 // Post an aysnc message to kill the application
5410 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5411 msg.arg1 = uid;
5412 msg.arg2 = 0;
5413 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005414 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005415 } else {
5416 throw new SecurityException(callerUid + " cannot kill pkg: " +
5417 pkg);
5418 }
5419 }
5420
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005421 public void closeSystemDialogs(String reason) {
5422 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5423 if (reason != null) {
5424 intent.putExtra("reason", reason);
5425 }
5426
5427 final int uid = Binder.getCallingUid();
5428 final long origId = Binder.clearCallingIdentity();
5429 synchronized (this) {
5430 int i = mWatchers.beginBroadcast();
5431 while (i > 0) {
5432 i--;
5433 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5434 if (w != null) {
5435 try {
5436 w.closingSystemDialogs(reason);
5437 } catch (RemoteException e) {
5438 }
5439 }
5440 }
5441 mWatchers.finishBroadcast();
5442
Dianne Hackbornffa42482009-09-23 22:20:11 -07005443 mWindowManager.closeSystemDialogs(reason);
5444
5445 for (i=mHistory.size()-1; i>=0; i--) {
5446 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5447 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5448 finishActivityLocked(r, i,
5449 Activity.RESULT_CANCELED, null, "close-sys");
5450 }
5451 }
5452
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005453 broadcastIntentLocked(null, null, intent, null,
5454 null, 0, null, null, null, false, false, -1, uid);
5455 }
5456 Binder.restoreCallingIdentity(origId);
5457 }
5458
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005459 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005460 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005461 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5462 for (int i=pids.length-1; i>=0; i--) {
5463 infos[i] = new Debug.MemoryInfo();
5464 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005465 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005466 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005467 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005468
5469 public void killApplicationProcess(String processName, int uid) {
5470 if (processName == null) {
5471 return;
5472 }
5473
5474 int callerUid = Binder.getCallingUid();
5475 // Only the system server can kill an application
5476 if (callerUid == Process.SYSTEM_UID) {
5477 synchronized (this) {
5478 ProcessRecord app = getProcessRecordLocked(processName, uid);
5479 if (app != null) {
5480 try {
5481 app.thread.scheduleSuicide();
5482 } catch (RemoteException e) {
5483 // If the other end already died, then our work here is done.
5484 }
5485 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005486 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005487 + processName + " / " + uid);
5488 }
5489 }
5490 } else {
5491 throw new SecurityException(callerUid + " cannot kill app process: " +
5492 processName);
5493 }
5494 }
5495
Dianne Hackborn03abb812010-01-04 18:43:19 -08005496 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005497 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5499 Uri.fromParts("package", packageName, null));
5500 intent.putExtra(Intent.EXTRA_UID, uid);
5501 broadcastIntentLocked(null, null, intent,
5502 null, null, 0, null, null, null,
5503 false, false, MY_PID, Process.SYSTEM_UID);
5504 }
5505
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005506 private final boolean killPackageProcessesLocked(String packageName, int uid,
5507 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005508 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509
Dianne Hackborn03abb812010-01-04 18:43:19 -08005510 // Remove all processes this package may have touched: all with the
5511 // same UID (except for the system or root user), and all whose name
5512 // matches the package name.
5513 final String procNamePrefix = packageName + ":";
5514 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5515 final int NA = apps.size();
5516 for (int ia=0; ia<NA; ia++) {
5517 ProcessRecord app = apps.valueAt(ia);
5518 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005519 if (doit) {
5520 procs.add(app);
5521 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005522 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5523 || app.processName.equals(packageName)
5524 || app.processName.startsWith(procNamePrefix)) {
5525 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005526 if (!doit) {
5527 return true;
5528 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005529 app.removed = true;
5530 procs.add(app);
5531 }
5532 }
5533 }
5534 }
5535
5536 int N = procs.size();
5537 for (int i=0; i<N; i++) {
5538 removeProcessLocked(procs.get(i), callerWillRestart);
5539 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005540 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005541 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005542
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005543 private final boolean forceStopPackageLocked(String name, int uid,
5544 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005545 int i, N;
5546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005547 if (uid < 0) {
5548 try {
5549 uid = ActivityThread.getPackageManager().getPackageUid(name);
5550 } catch (RemoteException e) {
5551 }
5552 }
5553
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005554 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005555 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005556
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005557 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5558 while (badApps.hasNext()) {
5559 SparseArray<Long> ba = badApps.next();
5560 if (ba.get(uid) != null) {
5561 badApps.remove();
5562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005563 }
5564 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005565
5566 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5567 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005568
5569 for (i=mHistory.size()-1; i>=0; i--) {
5570 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5571 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005572 if (!doit) {
5573 return true;
5574 }
5575 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005576 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005577 if (r.app != null) {
5578 r.app.removed = true;
5579 }
5580 r.app = null;
5581 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5582 }
5583 }
5584
5585 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5586 for (ServiceRecord service : mServices.values()) {
5587 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005588 if (!doit) {
5589 return true;
5590 }
5591 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005592 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005593 if (service.app != null) {
5594 service.app.removed = true;
5595 }
5596 service.app = null;
5597 services.add(service);
5598 }
5599 }
5600
5601 N = services.size();
5602 for (i=0; i<N; i++) {
5603 bringDownServiceLocked(services.get(i), true);
5604 }
5605
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005606 if (doit) {
5607 if (purgeCache) {
5608 AttributeCache ac = AttributeCache.instance();
5609 if (ac != null) {
5610 ac.removePackage(name);
5611 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005612 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005613 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005614 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005615
5616 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 }
5618
5619 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5620 final String name = app.processName;
5621 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005622 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 TAG, "Force removing process " + app + " (" + name
5624 + "/" + uid + ")");
5625
5626 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005627 if (mHeavyWeightProcess == app) {
5628 mHeavyWeightProcess = null;
5629 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 boolean needRestart = false;
5632 if (app.pid > 0 && app.pid != MY_PID) {
5633 int pid = app.pid;
5634 synchronized (mPidsSelfLocked) {
5635 mPidsSelfLocked.remove(pid);
5636 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5637 }
5638 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005639 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005640 Process.killProcess(pid);
5641
5642 if (app.persistent) {
5643 if (!callerWillRestart) {
5644 addAppLocked(app.info);
5645 } else {
5646 needRestart = true;
5647 }
5648 }
5649 } else {
5650 mRemovedProcesses.add(app);
5651 }
5652
5653 return needRestart;
5654 }
5655
5656 private final void processStartTimedOutLocked(ProcessRecord app) {
5657 final int pid = app.pid;
5658 boolean gone = false;
5659 synchronized (mPidsSelfLocked) {
5660 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5661 if (knownApp != null && knownApp.thread == null) {
5662 mPidsSelfLocked.remove(pid);
5663 gone = true;
5664 }
5665 }
5666
5667 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005668 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005669 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005670 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005672 if (mHeavyWeightProcess == app) {
5673 mHeavyWeightProcess = null;
5674 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5675 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005676 // Take care of any launching providers waiting for this process.
5677 checkAppInLaunchingProvidersLocked(app, true);
5678 // Take care of any services that are waiting for the process.
5679 for (int i=0; i<mPendingServices.size(); i++) {
5680 ServiceRecord sr = mPendingServices.get(i);
5681 if (app.info.uid == sr.appInfo.uid
5682 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005683 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005684 mPendingServices.remove(i);
5685 i--;
5686 bringDownServiceLocked(sr, true);
5687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005688 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005689 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005690 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005691 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005692 try {
5693 IBackupManager bm = IBackupManager.Stub.asInterface(
5694 ServiceManager.getService(Context.BACKUP_SERVICE));
5695 bm.agentDisconnected(app.info.packageName);
5696 } catch (RemoteException e) {
5697 // Can't happen; the backup manager is local
5698 }
5699 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005700 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005701 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005702 mPendingBroadcast = null;
5703 scheduleBroadcastsLocked();
5704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005705 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005706 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005707 }
5708 }
5709
5710 private final boolean attachApplicationLocked(IApplicationThread thread,
5711 int pid) {
5712
5713 // Find the application record that is being attached... either via
5714 // the pid if we are running in multiple processes, or just pull the
5715 // next app record if we are emulating process with anonymous threads.
5716 ProcessRecord app;
5717 if (pid != MY_PID && pid >= 0) {
5718 synchronized (mPidsSelfLocked) {
5719 app = mPidsSelfLocked.get(pid);
5720 }
5721 } else if (mStartingProcesses.size() > 0) {
5722 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005723 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 } else {
5725 app = null;
5726 }
5727
5728 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005729 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005731 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005732 if (pid > 0 && pid != MY_PID) {
5733 Process.killProcess(pid);
5734 } else {
5735 try {
5736 thread.scheduleExit();
5737 } catch (Exception e) {
5738 // Ignore exceptions.
5739 }
5740 }
5741 return false;
5742 }
5743
5744 // If this application record is still attached to a previous
5745 // process, clean it up now.
5746 if (app.thread != null) {
5747 handleAppDiedLocked(app, true);
5748 }
5749
5750 // Tell the process all about itself.
5751
Joe Onorato8a9b2202010-02-26 18:56:32 -08005752 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005753 TAG, "Binding process pid " + pid + " to record " + app);
5754
5755 String processName = app.processName;
5756 try {
5757 thread.asBinder().linkToDeath(new AppDeathRecipient(
5758 app, pid, thread), 0);
5759 } catch (RemoteException e) {
5760 app.resetPackageList();
5761 startProcessLocked(app, "link fail", processName);
5762 return false;
5763 }
5764
Doug Zongker2bec3d42009-12-04 12:52:44 -08005765 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005766
5767 app.thread = thread;
5768 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005769 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5770 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005771 app.forcingToForeground = null;
5772 app.foregroundServices = false;
5773 app.debugging = false;
5774
5775 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5776
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005777 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5778 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005779
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005780 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005781 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005782 }
5783
Joe Onorato8a9b2202010-02-26 18:56:32 -08005784 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005785 TAG, "New app record " + app
5786 + " thread=" + thread.asBinder() + " pid=" + pid);
5787 try {
5788 int testMode = IApplicationThread.DEBUG_OFF;
5789 if (mDebugApp != null && mDebugApp.equals(processName)) {
5790 testMode = mWaitForDebugger
5791 ? IApplicationThread.DEBUG_WAIT
5792 : IApplicationThread.DEBUG_ON;
5793 app.debugging = true;
5794 if (mDebugTransient) {
5795 mDebugApp = mOrigDebugApp;
5796 mWaitForDebugger = mOrigWaitForDebugger;
5797 }
5798 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005799
Christopher Tate181fafa2009-05-14 11:12:14 -07005800 // If the app is being launched for restore or full backup, set it up specially
5801 boolean isRestrictedBackupMode = false;
5802 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5803 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5804 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5805 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005806
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005807 ensurePackageDexOpt(app.instrumentationInfo != null
5808 ? app.instrumentationInfo.packageName
5809 : app.info.packageName);
5810 if (app.instrumentationClass != null) {
5811 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005812 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005813 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005814 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005815 thread.bindApplication(processName, app.instrumentationInfo != null
5816 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005817 app.instrumentationClass, app.instrumentationProfileFile,
5818 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005819 isRestrictedBackupMode || !normalMode,
5820 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005821 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005822 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005823 } catch (Exception e) {
5824 // todo: Yikes! What should we do? For now we will try to
5825 // start another process, but that could easily get us in
5826 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005827 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828
5829 app.resetPackageList();
5830 startProcessLocked(app, "bind fail", processName);
5831 return false;
5832 }
5833
5834 // Remove this record from the list of starting applications.
5835 mPersistentStartingProcesses.remove(app);
5836 mProcessesOnHold.remove(app);
5837
5838 boolean badApp = false;
5839 boolean didSomething = false;
5840
5841 // See if the top visible activity is waiting to run in this process...
5842 HistoryRecord hr = topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07005843 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005844 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5845 && processName.equals(hr.processName)) {
5846 try {
5847 if (realStartActivityLocked(hr, app, true, true)) {
5848 didSomething = true;
5849 }
5850 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005851 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005852 + hr.intent.getComponent().flattenToShortString(), e);
5853 badApp = true;
5854 }
5855 } else {
5856 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5857 }
5858 }
5859
5860 // Find any services that should be running in this process...
5861 if (!badApp && mPendingServices.size() > 0) {
5862 ServiceRecord sr = null;
5863 try {
5864 for (int i=0; i<mPendingServices.size(); i++) {
5865 sr = mPendingServices.get(i);
5866 if (app.info.uid != sr.appInfo.uid
5867 || !processName.equals(sr.processName)) {
5868 continue;
5869 }
5870
5871 mPendingServices.remove(i);
5872 i--;
5873 realStartServiceLocked(sr, app);
5874 didSomething = true;
5875 }
5876 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005877 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 + sr.shortName, e);
5879 badApp = true;
5880 }
5881 }
5882
5883 // Check if the next broadcast receiver is in this process...
5884 BroadcastRecord br = mPendingBroadcast;
5885 if (!badApp && br != null && br.curApp == app) {
5886 try {
5887 mPendingBroadcast = null;
5888 processCurBroadcastLocked(br, app);
5889 didSomething = true;
5890 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005891 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005892 + br.curComponent.flattenToShortString(), e);
5893 badApp = true;
5894 logBroadcastReceiverDiscard(br);
5895 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5896 br.resultExtras, br.resultAbort, true);
5897 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005898 // We need to reset the state if we fails to start the receiver.
5899 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005900 }
5901 }
5902
Christopher Tate181fafa2009-05-14 11:12:14 -07005903 // Check whether the next backup agent is in this process...
5904 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005905 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005906 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005907 try {
5908 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5909 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005910 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005911 e.printStackTrace();
5912 }
5913 }
5914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 if (badApp) {
5916 // todo: Also need to kill application to deal with all
5917 // kinds of exceptions.
5918 handleAppDiedLocked(app, false);
5919 return false;
5920 }
5921
5922 if (!didSomething) {
5923 updateOomAdjLocked();
5924 }
5925
5926 return true;
5927 }
5928
5929 public final void attachApplication(IApplicationThread thread) {
5930 synchronized (this) {
5931 int callingPid = Binder.getCallingPid();
5932 final long origId = Binder.clearCallingIdentity();
5933 attachApplicationLocked(thread, callingPid);
5934 Binder.restoreCallingIdentity(origId);
5935 }
5936 }
5937
Dianne Hackborne88846e2009-09-30 21:34:25 -07005938 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005939 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005940 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 Binder.restoreCallingIdentity(origId);
5942 }
5943
5944 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5945 boolean remove) {
5946 int N = mStoppingActivities.size();
5947 if (N <= 0) return null;
5948
5949 ArrayList<HistoryRecord> stops = null;
5950
5951 final boolean nowVisible = mResumedActivity != null
5952 && mResumedActivity.nowVisible
5953 && !mResumedActivity.waitingVisible;
5954 for (int i=0; i<N; i++) {
5955 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005956 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 + nowVisible + " waitingVisible=" + s.waitingVisible
5958 + " finishing=" + s.finishing);
5959 if (s.waitingVisible && nowVisible) {
5960 mWaitingVisibleActivities.remove(s);
5961 s.waitingVisible = false;
5962 if (s.finishing) {
5963 // If this activity is finishing, it is sitting on top of
5964 // everyone else but we now know it is no longer needed...
5965 // so get rid of it. Otherwise, we need to go through the
5966 // normal flow and hide it once we determine that it is
5967 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005968 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005969 mWindowManager.setAppVisibility(s, false);
5970 }
5971 }
5972 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005973 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005974 if (stops == null) {
5975 stops = new ArrayList<HistoryRecord>();
5976 }
5977 stops.add(s);
5978 mStoppingActivities.remove(i);
5979 N--;
5980 i--;
5981 }
5982 }
5983
5984 return stops;
5985 }
5986
5987 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005988 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005989 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005990 mWindowManager.enableScreenAfterBoot();
5991 }
5992
Dianne Hackborne88846e2009-09-30 21:34:25 -07005993 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5994 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005995 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996
5997 ArrayList<HistoryRecord> stops = null;
5998 ArrayList<HistoryRecord> finishes = null;
5999 ArrayList<HistoryRecord> thumbnails = null;
6000 int NS = 0;
6001 int NF = 0;
6002 int NT = 0;
6003 IApplicationThread sendThumbnail = null;
6004 boolean booting = false;
6005 boolean enableScreen = false;
6006
6007 synchronized (this) {
6008 if (token != null) {
6009 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
6010 }
6011
6012 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07006013 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006014 if (index >= 0) {
6015 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6016
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006017 if (fromTimeout) {
6018 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
6019 }
6020
Dianne Hackborne88846e2009-09-30 21:34:25 -07006021 // This is a hack to semi-deal with a race condition
6022 // in the client where it can be constructed with a
6023 // newer configuration from when we asked it to launch.
6024 // We'll update with whatever configuration it now says
6025 // it used to launch.
6026 if (config != null) {
6027 r.configuration = config;
6028 }
6029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006030 // No longer need to keep the device awake.
6031 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
6032 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
6033 mLaunchingActivity.release();
6034 }
6035
6036 // We are now idle. If someone is waiting for a thumbnail from
6037 // us, we can now deliver.
6038 r.idle = true;
6039 scheduleAppGcsLocked();
6040 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
6041 sendThumbnail = r.app.thread;
6042 r.thumbnailNeeded = false;
6043 }
6044
6045 // If this activity is fullscreen, set up to hide those under it.
6046
Joe Onorato8a9b2202010-02-26 18:56:32 -08006047 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 ensureActivitiesVisibleLocked(null, 0);
6049
Joe Onorato8a9b2202010-02-26 18:56:32 -08006050 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006051 if (!mBooted && !fromTimeout) {
6052 mBooted = true;
6053 enableScreen = true;
6054 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006055
6056 } else if (fromTimeout) {
6057 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006058 }
6059
6060 // Atomically retrieve all of the other things to do.
6061 stops = processStoppingActivitiesLocked(true);
6062 NS = stops != null ? stops.size() : 0;
6063 if ((NF=mFinishingActivities.size()) > 0) {
6064 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
6065 mFinishingActivities.clear();
6066 }
6067 if ((NT=mCancelledThumbnails.size()) > 0) {
6068 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
6069 mCancelledThumbnails.clear();
6070 }
6071
6072 booting = mBooting;
6073 mBooting = false;
6074 }
6075
6076 int i;
6077
6078 // Send thumbnail if requested.
6079 if (sendThumbnail != null) {
6080 try {
6081 sendThumbnail.requestThumbnail(token);
6082 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006083 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006084 sendPendingThumbnail(null, token, null, null, true);
6085 }
6086 }
6087
6088 // Stop any activities that are scheduled to do so but have been
6089 // waiting for the next one to start.
6090 for (i=0; i<NS; i++) {
6091 HistoryRecord r = (HistoryRecord)stops.get(i);
6092 synchronized (this) {
6093 if (r.finishing) {
6094 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
6095 } else {
6096 stopActivityLocked(r);
6097 }
6098 }
6099 }
6100
6101 // Finish any activities that are scheduled to do so but have been
6102 // waiting for the next one to start.
6103 for (i=0; i<NF; i++) {
6104 HistoryRecord r = (HistoryRecord)finishes.get(i);
6105 synchronized (this) {
6106 destroyActivityLocked(r, true);
6107 }
6108 }
6109
6110 // Report back to any thumbnail receivers.
6111 for (i=0; i<NT; i++) {
6112 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
6113 sendPendingThumbnail(r, null, null, null, true);
6114 }
6115
6116 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006117 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006118 }
6119
6120 trimApplications();
6121 //dump();
6122 //mWindowManager.dump();
6123
6124 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006125 enableScreenAfterBoot();
6126 }
6127 }
6128
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006129 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006130 IntentFilter pkgFilter = new IntentFilter();
6131 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
6132 pkgFilter.addDataScheme("package");
6133 mContext.registerReceiver(new BroadcastReceiver() {
6134 @Override
6135 public void onReceive(Context context, Intent intent) {
6136 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
6137 if (pkgs != null) {
6138 for (String pkg : pkgs) {
6139 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
6140 setResultCode(Activity.RESULT_OK);
6141 return;
6142 }
6143 }
6144 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006145 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006146 }, pkgFilter);
6147
6148 synchronized (this) {
6149 // Ensure that any processes we had put on hold are now started
6150 // up.
6151 final int NP = mProcessesOnHold.size();
6152 if (NP > 0) {
6153 ArrayList<ProcessRecord> procs =
6154 new ArrayList<ProcessRecord>(mProcessesOnHold);
6155 for (int ip=0; ip<NP; ip++) {
6156 this.startProcessLocked(procs.get(ip), "on-hold", null);
6157 }
6158 }
6159
6160 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6161 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006162 broadcastIntentLocked(null, null,
6163 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
6164 null, null, 0, null, null,
6165 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
6166 false, false, MY_PID, Process.SYSTEM_UID);
6167 }
6168 }
6169 }
6170
6171 final void ensureBootCompleted() {
6172 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006173 boolean enableScreen;
6174 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006175 booting = mBooting;
6176 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006177 enableScreen = !mBooted;
6178 mBooted = true;
6179 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006180
6181 if (booting) {
6182 finishBooting();
6183 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006184
6185 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006186 enableScreenAfterBoot();
6187 }
6188 }
6189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006190 public final void activityPaused(IBinder token, Bundle icicle) {
6191 // Refuse possible leaked file descriptors
6192 if (icicle != null && icicle.hasFileDescriptors()) {
6193 throw new IllegalArgumentException("File descriptors passed in Bundle");
6194 }
6195
6196 final long origId = Binder.clearCallingIdentity();
6197 activityPaused(token, icicle, false);
6198 Binder.restoreCallingIdentity(origId);
6199 }
6200
6201 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006202 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006203 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
6204 + ", timeout=" + timeout);
6205
6206 HistoryRecord r = null;
6207
6208 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006209 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006210 if (index >= 0) {
6211 r = (HistoryRecord)mHistory.get(index);
6212 if (!timeout) {
6213 r.icicle = icicle;
6214 r.haveState = true;
6215 }
6216 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
6217 if (mPausingActivity == r) {
6218 r.state = ActivityState.PAUSED;
6219 completePauseLocked();
6220 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08006221 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006222 System.identityHashCode(r), r.shortComponentName,
6223 mPausingActivity != null
6224 ? mPausingActivity.shortComponentName : "(none)");
6225 }
6226 }
6227 }
6228 }
6229
6230 public final void activityStopped(IBinder token, Bitmap thumbnail,
6231 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006232 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006233 TAG, "Activity stopped: token=" + token);
6234
6235 HistoryRecord r = null;
6236
6237 final long origId = Binder.clearCallingIdentity();
6238
6239 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006240 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006241 if (index >= 0) {
6242 r = (HistoryRecord)mHistory.get(index);
6243 r.thumbnail = thumbnail;
6244 r.description = description;
6245 r.stopped = true;
6246 r.state = ActivityState.STOPPED;
6247 if (!r.finishing) {
6248 if (r.configDestroy) {
6249 destroyActivityLocked(r, true);
6250 resumeTopActivityLocked(null);
6251 }
6252 }
6253 }
6254 }
6255
6256 if (r != null) {
6257 sendPendingThumbnail(r, null, null, null, false);
6258 }
6259
6260 trimApplications();
6261
6262 Binder.restoreCallingIdentity(origId);
6263 }
6264
6265 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006266 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006267 synchronized (this) {
6268 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
6269
Dianne Hackborn75b03852009-06-12 15:43:26 -07006270 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006271 if (index >= 0) {
6272 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6273 if (r.state == ActivityState.DESTROYING) {
6274 final long origId = Binder.clearCallingIdentity();
6275 removeActivityFromHistoryLocked(r);
6276 Binder.restoreCallingIdentity(origId);
6277 }
6278 }
6279 }
6280 }
6281
6282 public String getCallingPackage(IBinder token) {
6283 synchronized (this) {
6284 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07006285 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006286 }
6287 }
6288
6289 public ComponentName getCallingActivity(IBinder token) {
6290 synchronized (this) {
6291 HistoryRecord r = getCallingRecordLocked(token);
6292 return r != null ? r.intent.getComponent() : null;
6293 }
6294 }
6295
6296 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006297 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006298 if (index >= 0) {
6299 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6300 if (r != null) {
6301 return r.resultTo;
6302 }
6303 }
6304 return null;
6305 }
6306
6307 public ComponentName getActivityClassForToken(IBinder token) {
6308 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006309 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006310 if (index >= 0) {
6311 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6312 return r.intent.getComponent();
6313 }
6314 return null;
6315 }
6316 }
6317
6318 public String getPackageForToken(IBinder token) {
6319 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006320 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006321 if (index >= 0) {
6322 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6323 return r.packageName;
6324 }
6325 return null;
6326 }
6327 }
6328
6329 public IIntentSender getIntentSender(int type,
6330 String packageName, IBinder token, String resultWho,
6331 int requestCode, Intent intent, String resolvedType, int flags) {
6332 // Refuse possible leaked file descriptors
6333 if (intent != null && intent.hasFileDescriptors() == true) {
6334 throw new IllegalArgumentException("File descriptors passed in Intent");
6335 }
6336
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006337 if (type == INTENT_SENDER_BROADCAST) {
6338 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6339 throw new IllegalArgumentException(
6340 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6341 }
6342 }
6343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006344 synchronized(this) {
6345 int callingUid = Binder.getCallingUid();
6346 try {
6347 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6348 Process.supportsProcesses()) {
6349 int uid = ActivityThread.getPackageManager()
6350 .getPackageUid(packageName);
6351 if (uid != Binder.getCallingUid()) {
6352 String msg = "Permission Denial: getIntentSender() from pid="
6353 + Binder.getCallingPid()
6354 + ", uid=" + Binder.getCallingUid()
6355 + ", (need uid=" + uid + ")"
6356 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006357 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006358 throw new SecurityException(msg);
6359 }
6360 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006361
6362 return getIntentSenderLocked(type, packageName, callingUid,
6363 token, resultWho, requestCode, intent, resolvedType, flags);
6364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006365 } catch (RemoteException e) {
6366 throw new SecurityException(e);
6367 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006368 }
6369 }
6370
6371 IIntentSender getIntentSenderLocked(int type,
6372 String packageName, int callingUid, IBinder token, String resultWho,
6373 int requestCode, Intent intent, String resolvedType, int flags) {
6374 HistoryRecord activity = null;
6375 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6376 int index = indexOfTokenLocked(token);
6377 if (index < 0) {
6378 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006379 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006380 activity = (HistoryRecord)mHistory.get(index);
6381 if (activity.finishing) {
6382 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006383 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006384 }
6385
6386 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6387 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6388 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6389 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6390 |PendingIntent.FLAG_UPDATE_CURRENT);
6391
6392 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6393 type, packageName, activity, resultWho,
6394 requestCode, intent, resolvedType, flags);
6395 WeakReference<PendingIntentRecord> ref;
6396 ref = mIntentSenderRecords.get(key);
6397 PendingIntentRecord rec = ref != null ? ref.get() : null;
6398 if (rec != null) {
6399 if (!cancelCurrent) {
6400 if (updateCurrent) {
6401 rec.key.requestIntent.replaceExtras(intent);
6402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006403 return rec;
6404 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006405 rec.canceled = true;
6406 mIntentSenderRecords.remove(key);
6407 }
6408 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006409 return rec;
6410 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006411 rec = new PendingIntentRecord(this, key, callingUid);
6412 mIntentSenderRecords.put(key, rec.ref);
6413 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6414 if (activity.pendingResults == null) {
6415 activity.pendingResults
6416 = new HashSet<WeakReference<PendingIntentRecord>>();
6417 }
6418 activity.pendingResults.add(rec.ref);
6419 }
6420 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006421 }
6422
6423 public void cancelIntentSender(IIntentSender sender) {
6424 if (!(sender instanceof PendingIntentRecord)) {
6425 return;
6426 }
6427 synchronized(this) {
6428 PendingIntentRecord rec = (PendingIntentRecord)sender;
6429 try {
6430 int uid = ActivityThread.getPackageManager()
6431 .getPackageUid(rec.key.packageName);
6432 if (uid != Binder.getCallingUid()) {
6433 String msg = "Permission Denial: cancelIntentSender() from pid="
6434 + Binder.getCallingPid()
6435 + ", uid=" + Binder.getCallingUid()
6436 + " is not allowed to cancel packges "
6437 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006438 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006439 throw new SecurityException(msg);
6440 }
6441 } catch (RemoteException e) {
6442 throw new SecurityException(e);
6443 }
6444 cancelIntentSenderLocked(rec, true);
6445 }
6446 }
6447
6448 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6449 rec.canceled = true;
6450 mIntentSenderRecords.remove(rec.key);
6451 if (cleanActivity && rec.key.activity != null) {
6452 rec.key.activity.pendingResults.remove(rec.ref);
6453 }
6454 }
6455
6456 public String getPackageForIntentSender(IIntentSender pendingResult) {
6457 if (!(pendingResult instanceof PendingIntentRecord)) {
6458 return null;
6459 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006460 try {
6461 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6462 return res.key.packageName;
6463 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006464 }
6465 return null;
6466 }
6467
6468 public void setProcessLimit(int max) {
6469 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6470 "setProcessLimit()");
6471 mProcessLimit = max;
6472 }
6473
6474 public int getProcessLimit() {
6475 return mProcessLimit;
6476 }
6477
6478 void foregroundTokenDied(ForegroundToken token) {
6479 synchronized (ActivityManagerService.this) {
6480 synchronized (mPidsSelfLocked) {
6481 ForegroundToken cur
6482 = mForegroundProcesses.get(token.pid);
6483 if (cur != token) {
6484 return;
6485 }
6486 mForegroundProcesses.remove(token.pid);
6487 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6488 if (pr == null) {
6489 return;
6490 }
6491 pr.forcingToForeground = null;
6492 pr.foregroundServices = false;
6493 }
6494 updateOomAdjLocked();
6495 }
6496 }
6497
6498 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6499 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6500 "setProcessForeground()");
6501 synchronized(this) {
6502 boolean changed = false;
6503
6504 synchronized (mPidsSelfLocked) {
6505 ProcessRecord pr = mPidsSelfLocked.get(pid);
6506 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006507 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006508 return;
6509 }
6510 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6511 if (oldToken != null) {
6512 oldToken.token.unlinkToDeath(oldToken, 0);
6513 mForegroundProcesses.remove(pid);
6514 pr.forcingToForeground = null;
6515 changed = true;
6516 }
6517 if (isForeground && token != null) {
6518 ForegroundToken newToken = new ForegroundToken() {
6519 public void binderDied() {
6520 foregroundTokenDied(this);
6521 }
6522 };
6523 newToken.pid = pid;
6524 newToken.token = token;
6525 try {
6526 token.linkToDeath(newToken, 0);
6527 mForegroundProcesses.put(pid, newToken);
6528 pr.forcingToForeground = token;
6529 changed = true;
6530 } catch (RemoteException e) {
6531 // If the process died while doing this, we will later
6532 // do the cleanup with the process death link.
6533 }
6534 }
6535 }
6536
6537 if (changed) {
6538 updateOomAdjLocked();
6539 }
6540 }
6541 }
6542
6543 // =========================================================
6544 // PERMISSIONS
6545 // =========================================================
6546
6547 static class PermissionController extends IPermissionController.Stub {
6548 ActivityManagerService mActivityManagerService;
6549 PermissionController(ActivityManagerService activityManagerService) {
6550 mActivityManagerService = activityManagerService;
6551 }
6552
6553 public boolean checkPermission(String permission, int pid, int uid) {
6554 return mActivityManagerService.checkPermission(permission, pid,
6555 uid) == PackageManager.PERMISSION_GRANTED;
6556 }
6557 }
6558
6559 /**
6560 * This can be called with or without the global lock held.
6561 */
6562 int checkComponentPermission(String permission, int pid, int uid,
6563 int reqUid) {
6564 // We might be performing an operation on behalf of an indirect binder
6565 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6566 // client identity accordingly before proceeding.
6567 Identity tlsIdentity = sCallerIdentity.get();
6568 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006569 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006570 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6571 uid = tlsIdentity.uid;
6572 pid = tlsIdentity.pid;
6573 }
6574
6575 // Root, system server and our own process get to do everything.
6576 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6577 !Process.supportsProcesses()) {
6578 return PackageManager.PERMISSION_GRANTED;
6579 }
6580 // If the target requires a specific UID, always fail for others.
6581 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006582 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006583 return PackageManager.PERMISSION_DENIED;
6584 }
6585 if (permission == null) {
6586 return PackageManager.PERMISSION_GRANTED;
6587 }
6588 try {
6589 return ActivityThread.getPackageManager()
6590 .checkUidPermission(permission, uid);
6591 } catch (RemoteException e) {
6592 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006593 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006594 }
6595 return PackageManager.PERMISSION_DENIED;
6596 }
6597
6598 /**
6599 * As the only public entry point for permissions checking, this method
6600 * can enforce the semantic that requesting a check on a null global
6601 * permission is automatically denied. (Internally a null permission
6602 * string is used when calling {@link #checkComponentPermission} in cases
6603 * when only uid-based security is needed.)
6604 *
6605 * This can be called with or without the global lock held.
6606 */
6607 public int checkPermission(String permission, int pid, int uid) {
6608 if (permission == null) {
6609 return PackageManager.PERMISSION_DENIED;
6610 }
6611 return checkComponentPermission(permission, pid, uid, -1);
6612 }
6613
6614 /**
6615 * Binder IPC calls go through the public entry point.
6616 * This can be called with or without the global lock held.
6617 */
6618 int checkCallingPermission(String permission) {
6619 return checkPermission(permission,
6620 Binder.getCallingPid(),
6621 Binder.getCallingUid());
6622 }
6623
6624 /**
6625 * This can be called with or without the global lock held.
6626 */
6627 void enforceCallingPermission(String permission, String func) {
6628 if (checkCallingPermission(permission)
6629 == PackageManager.PERMISSION_GRANTED) {
6630 return;
6631 }
6632
6633 String msg = "Permission Denial: " + func + " from pid="
6634 + Binder.getCallingPid()
6635 + ", uid=" + Binder.getCallingUid()
6636 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006637 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006638 throw new SecurityException(msg);
6639 }
6640
6641 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6642 ProviderInfo pi, int uid, int modeFlags) {
6643 try {
6644 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6645 if ((pi.readPermission != null) &&
6646 (pm.checkUidPermission(pi.readPermission, uid)
6647 != PackageManager.PERMISSION_GRANTED)) {
6648 return false;
6649 }
6650 }
6651 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6652 if ((pi.writePermission != null) &&
6653 (pm.checkUidPermission(pi.writePermission, uid)
6654 != PackageManager.PERMISSION_GRANTED)) {
6655 return false;
6656 }
6657 }
6658 return true;
6659 } catch (RemoteException e) {
6660 return false;
6661 }
6662 }
6663
6664 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6665 int modeFlags) {
6666 // Root gets to do everything.
6667 if (uid == 0 || !Process.supportsProcesses()) {
6668 return true;
6669 }
6670 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6671 if (perms == null) return false;
6672 UriPermission perm = perms.get(uri);
6673 if (perm == null) return false;
6674 return (modeFlags&perm.modeFlags) == modeFlags;
6675 }
6676
6677 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6678 // Another redirected-binder-call permissions check as in
6679 // {@link checkComponentPermission}.
6680 Identity tlsIdentity = sCallerIdentity.get();
6681 if (tlsIdentity != null) {
6682 uid = tlsIdentity.uid;
6683 pid = tlsIdentity.pid;
6684 }
6685
6686 // Our own process gets to do everything.
6687 if (pid == MY_PID) {
6688 return PackageManager.PERMISSION_GRANTED;
6689 }
6690 synchronized(this) {
6691 return checkUriPermissionLocked(uri, uid, modeFlags)
6692 ? PackageManager.PERMISSION_GRANTED
6693 : PackageManager.PERMISSION_DENIED;
6694 }
6695 }
6696
6697 private void grantUriPermissionLocked(int callingUid,
6698 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6699 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6700 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6701 if (modeFlags == 0) {
6702 return;
6703 }
6704
Joe Onorato8a9b2202010-02-26 18:56:32 -08006705 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006706 "Requested grant " + targetPkg + " permission to " + uri);
6707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006708 final IPackageManager pm = ActivityThread.getPackageManager();
6709
6710 // If this is not a content: uri, we can't do anything with it.
6711 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006712 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006713 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006714 return;
6715 }
6716
6717 String name = uri.getAuthority();
6718 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006719 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006720 if (cpr != null) {
6721 pi = cpr.info;
6722 } else {
6723 try {
6724 pi = pm.resolveContentProvider(name,
6725 PackageManager.GET_URI_PERMISSION_PATTERNS);
6726 } catch (RemoteException ex) {
6727 }
6728 }
6729 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006730 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006731 return;
6732 }
6733
6734 int targetUid;
6735 try {
6736 targetUid = pm.getPackageUid(targetPkg);
6737 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006738 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006739 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006740 return;
6741 }
6742 } catch (RemoteException ex) {
6743 return;
6744 }
6745
6746 // First... does the target actually need this permission?
6747 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6748 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006749 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006750 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006751 return;
6752 }
6753
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006754 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006755 if (!pi.grantUriPermissions) {
6756 throw new SecurityException("Provider " + pi.packageName
6757 + "/" + pi.name
6758 + " does not allow granting of Uri permissions (uri "
6759 + uri + ")");
6760 }
6761 if (pi.uriPermissionPatterns != null) {
6762 final int N = pi.uriPermissionPatterns.length;
6763 boolean allowed = false;
6764 for (int i=0; i<N; i++) {
6765 if (pi.uriPermissionPatterns[i] != null
6766 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6767 allowed = true;
6768 break;
6769 }
6770 }
6771 if (!allowed) {
6772 throw new SecurityException("Provider " + pi.packageName
6773 + "/" + pi.name
6774 + " does not allow granting of permission to path of Uri "
6775 + uri);
6776 }
6777 }
6778
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006779 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006780 // this uri?
6781 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6782 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6783 throw new SecurityException("Uid " + callingUid
6784 + " does not have permission to uri " + uri);
6785 }
6786 }
6787
6788 // Okay! So here we are: the caller has the assumed permission
6789 // to the uri, and the target doesn't. Let's now give this to
6790 // the target.
6791
Joe Onorato8a9b2202010-02-26 18:56:32 -08006792 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006793 "Granting " + targetPkg + " permission to " + uri);
6794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006795 HashMap<Uri, UriPermission> targetUris
6796 = mGrantedUriPermissions.get(targetUid);
6797 if (targetUris == null) {
6798 targetUris = new HashMap<Uri, UriPermission>();
6799 mGrantedUriPermissions.put(targetUid, targetUris);
6800 }
6801
6802 UriPermission perm = targetUris.get(uri);
6803 if (perm == null) {
6804 perm = new UriPermission(targetUid, uri);
6805 targetUris.put(uri, perm);
6806
6807 }
6808 perm.modeFlags |= modeFlags;
6809 if (activity == null) {
6810 perm.globalModeFlags |= modeFlags;
6811 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6812 perm.readActivities.add(activity);
6813 if (activity.readUriPermissions == null) {
6814 activity.readUriPermissions = new HashSet<UriPermission>();
6815 }
6816 activity.readUriPermissions.add(perm);
6817 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6818 perm.writeActivities.add(activity);
6819 if (activity.writeUriPermissions == null) {
6820 activity.writeUriPermissions = new HashSet<UriPermission>();
6821 }
6822 activity.writeUriPermissions.add(perm);
6823 }
6824 }
6825
6826 private void grantUriPermissionFromIntentLocked(int callingUid,
6827 String targetPkg, Intent intent, HistoryRecord activity) {
6828 if (intent == null) {
6829 return;
6830 }
6831 Uri data = intent.getData();
6832 if (data == null) {
6833 return;
6834 }
6835 grantUriPermissionLocked(callingUid, targetPkg, data,
6836 intent.getFlags(), activity);
6837 }
6838
6839 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6840 Uri uri, int modeFlags) {
6841 synchronized(this) {
6842 final ProcessRecord r = getRecordForAppLocked(caller);
6843 if (r == null) {
6844 throw new SecurityException("Unable to find app for caller "
6845 + caller
6846 + " when granting permission to uri " + uri);
6847 }
6848 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006849 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006850 return;
6851 }
6852 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006853 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854 return;
6855 }
6856
6857 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6858 null);
6859 }
6860 }
6861
6862 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6863 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6864 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6865 HashMap<Uri, UriPermission> perms
6866 = mGrantedUriPermissions.get(perm.uid);
6867 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006868 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006869 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006870 perms.remove(perm.uri);
6871 if (perms.size() == 0) {
6872 mGrantedUriPermissions.remove(perm.uid);
6873 }
6874 }
6875 }
6876 }
6877
6878 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6879 if (activity.readUriPermissions != null) {
6880 for (UriPermission perm : activity.readUriPermissions) {
6881 perm.readActivities.remove(activity);
6882 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6883 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6884 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6885 removeUriPermissionIfNeededLocked(perm);
6886 }
6887 }
6888 }
6889 if (activity.writeUriPermissions != null) {
6890 for (UriPermission perm : activity.writeUriPermissions) {
6891 perm.writeActivities.remove(activity);
6892 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6893 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6894 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6895 removeUriPermissionIfNeededLocked(perm);
6896 }
6897 }
6898 }
6899 }
6900
6901 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6902 int modeFlags) {
6903 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6904 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6905 if (modeFlags == 0) {
6906 return;
6907 }
6908
Joe Onorato8a9b2202010-02-26 18:56:32 -08006909 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006910 "Revoking all granted permissions to " + uri);
6911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006912 final IPackageManager pm = ActivityThread.getPackageManager();
6913
6914 final String authority = uri.getAuthority();
6915 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006916 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006917 if (cpr != null) {
6918 pi = cpr.info;
6919 } else {
6920 try {
6921 pi = pm.resolveContentProvider(authority,
6922 PackageManager.GET_URI_PERMISSION_PATTERNS);
6923 } catch (RemoteException ex) {
6924 }
6925 }
6926 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006927 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006928 return;
6929 }
6930
6931 // Does the caller have this permission on the URI?
6932 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6933 // Right now, if you are not the original owner of the permission,
6934 // you are not allowed to revoke it.
6935 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6936 throw new SecurityException("Uid " + callingUid
6937 + " does not have permission to uri " + uri);
6938 //}
6939 }
6940
6941 // Go through all of the permissions and remove any that match.
6942 final List<String> SEGMENTS = uri.getPathSegments();
6943 if (SEGMENTS != null) {
6944 final int NS = SEGMENTS.size();
6945 int N = mGrantedUriPermissions.size();
6946 for (int i=0; i<N; i++) {
6947 HashMap<Uri, UriPermission> perms
6948 = mGrantedUriPermissions.valueAt(i);
6949 Iterator<UriPermission> it = perms.values().iterator();
6950 toploop:
6951 while (it.hasNext()) {
6952 UriPermission perm = it.next();
6953 Uri targetUri = perm.uri;
6954 if (!authority.equals(targetUri.getAuthority())) {
6955 continue;
6956 }
6957 List<String> targetSegments = targetUri.getPathSegments();
6958 if (targetSegments == null) {
6959 continue;
6960 }
6961 if (targetSegments.size() < NS) {
6962 continue;
6963 }
6964 for (int j=0; j<NS; j++) {
6965 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6966 continue toploop;
6967 }
6968 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006969 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006970 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006971 perm.clearModes(modeFlags);
6972 if (perm.modeFlags == 0) {
6973 it.remove();
6974 }
6975 }
6976 if (perms.size() == 0) {
6977 mGrantedUriPermissions.remove(
6978 mGrantedUriPermissions.keyAt(i));
6979 N--;
6980 i--;
6981 }
6982 }
6983 }
6984 }
6985
6986 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6987 int modeFlags) {
6988 synchronized(this) {
6989 final ProcessRecord r = getRecordForAppLocked(caller);
6990 if (r == null) {
6991 throw new SecurityException("Unable to find app for caller "
6992 + caller
6993 + " when revoking permission to uri " + uri);
6994 }
6995 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006996 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006997 return;
6998 }
6999
7000 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
7001 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
7002 if (modeFlags == 0) {
7003 return;
7004 }
7005
7006 final IPackageManager pm = ActivityThread.getPackageManager();
7007
7008 final String authority = uri.getAuthority();
7009 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07007010 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007011 if (cpr != null) {
7012 pi = cpr.info;
7013 } else {
7014 try {
7015 pi = pm.resolveContentProvider(authority,
7016 PackageManager.GET_URI_PERMISSION_PATTERNS);
7017 } catch (RemoteException ex) {
7018 }
7019 }
7020 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007021 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007022 return;
7023 }
7024
7025 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
7026 }
7027 }
7028
7029 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
7030 synchronized (this) {
7031 ProcessRecord app =
7032 who != null ? getRecordForAppLocked(who) : null;
7033 if (app == null) return;
7034
7035 Message msg = Message.obtain();
7036 msg.what = WAIT_FOR_DEBUGGER_MSG;
7037 msg.obj = app;
7038 msg.arg1 = waiting ? 1 : 0;
7039 mHandler.sendMessage(msg);
7040 }
7041 }
7042
7043 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
7044 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08007045 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007046 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08007047 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007048 }
7049
7050 // =========================================================
7051 // TASK MANAGEMENT
7052 // =========================================================
7053
7054 public List getTasks(int maxNum, int flags,
7055 IThumbnailReceiver receiver) {
7056 ArrayList list = new ArrayList();
7057
7058 PendingThumbnailsRecord pending = null;
7059 IApplicationThread topThumbnail = null;
7060 HistoryRecord topRecord = null;
7061
7062 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007063 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007064 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
7065 + ", receiver=" + receiver);
7066
7067 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
7068 != PackageManager.PERMISSION_GRANTED) {
7069 if (receiver != null) {
7070 // If the caller wants to wait for pending thumbnails,
7071 // it ain't gonna get them.
7072 try {
7073 receiver.finished();
7074 } catch (RemoteException ex) {
7075 }
7076 }
7077 String msg = "Permission Denial: getTasks() from pid="
7078 + Binder.getCallingPid()
7079 + ", uid=" + Binder.getCallingUid()
7080 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007081 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007082 throw new SecurityException(msg);
7083 }
7084
7085 int pos = mHistory.size()-1;
7086 HistoryRecord next =
7087 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
7088 HistoryRecord top = null;
7089 CharSequence topDescription = null;
7090 TaskRecord curTask = null;
7091 int numActivities = 0;
7092 int numRunning = 0;
7093 while (pos >= 0 && maxNum > 0) {
7094 final HistoryRecord r = next;
7095 pos--;
7096 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
7097
7098 // Initialize state for next task if needed.
7099 if (top == null ||
7100 (top.state == ActivityState.INITIALIZING
7101 && top.task == r.task)) {
7102 top = r;
7103 topDescription = r.description;
7104 curTask = r.task;
7105 numActivities = numRunning = 0;
7106 }
7107
7108 // Add 'r' into the current task.
7109 numActivities++;
7110 if (r.app != null && r.app.thread != null) {
7111 numRunning++;
7112 }
7113 if (topDescription == null) {
7114 topDescription = r.description;
7115 }
7116
Joe Onorato8a9b2202010-02-26 18:56:32 -08007117 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007118 TAG, r.intent.getComponent().flattenToShortString()
7119 + ": task=" + r.task);
7120
7121 // If the next one is a different task, generate a new
7122 // TaskInfo entry for what we have.
7123 if (next == null || next.task != curTask) {
7124 ActivityManager.RunningTaskInfo ci
7125 = new ActivityManager.RunningTaskInfo();
7126 ci.id = curTask.taskId;
7127 ci.baseActivity = r.intent.getComponent();
7128 ci.topActivity = top.intent.getComponent();
7129 ci.thumbnail = top.thumbnail;
7130 ci.description = topDescription;
7131 ci.numActivities = numActivities;
7132 ci.numRunning = numRunning;
7133 //System.out.println(
7134 // "#" + maxNum + ": " + " descr=" + ci.description);
7135 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007136 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 TAG, "State=" + top.state + "Idle=" + top.idle
7138 + " app=" + top.app
7139 + " thr=" + (top.app != null ? top.app.thread : null));
7140 if (top.state == ActivityState.RESUMED
7141 || top.state == ActivityState.PAUSING) {
7142 if (top.idle && top.app != null
7143 && top.app.thread != null) {
7144 topRecord = top;
7145 topThumbnail = top.app.thread;
7146 } else {
7147 top.thumbnailNeeded = true;
7148 }
7149 }
7150 if (pending == null) {
7151 pending = new PendingThumbnailsRecord(receiver);
7152 }
7153 pending.pendingRecords.add(top);
7154 }
7155 list.add(ci);
7156 maxNum--;
7157 top = null;
7158 }
7159 }
7160
7161 if (pending != null) {
7162 mPendingThumbnails.add(pending);
7163 }
7164 }
7165
Joe Onorato8a9b2202010-02-26 18:56:32 -08007166 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007167
7168 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007169 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007170 try {
7171 topThumbnail.requestThumbnail(topRecord);
7172 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007173 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007174 sendPendingThumbnail(null, topRecord, null, null, true);
7175 }
7176 }
7177
7178 if (pending == null && receiver != null) {
7179 // In this case all thumbnails were available and the client
7180 // is being asked to be told when the remaining ones come in...
7181 // which is unusually, since the top-most currently running
7182 // activity should never have a canned thumbnail! Oh well.
7183 try {
7184 receiver.finished();
7185 } catch (RemoteException ex) {
7186 }
7187 }
7188
7189 return list;
7190 }
7191
7192 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
7193 int flags) {
7194 synchronized (this) {
7195 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
7196 "getRecentTasks()");
7197
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007198 IPackageManager pm = ActivityThread.getPackageManager();
7199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007200 final int N = mRecentTasks.size();
7201 ArrayList<ActivityManager.RecentTaskInfo> res
7202 = new ArrayList<ActivityManager.RecentTaskInfo>(
7203 maxNum < N ? maxNum : N);
7204 for (int i=0; i<N && maxNum > 0; i++) {
7205 TaskRecord tr = mRecentTasks.get(i);
7206 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
7207 || (tr.intent == null)
7208 || ((tr.intent.getFlags()
7209 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
7210 ActivityManager.RecentTaskInfo rti
7211 = new ActivityManager.RecentTaskInfo();
7212 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
7213 rti.baseIntent = new Intent(
7214 tr.intent != null ? tr.intent : tr.affinityIntent);
7215 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007216
7217 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
7218 // Check whether this activity is currently available.
7219 try {
7220 if (rti.origActivity != null) {
7221 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
7222 continue;
7223 }
7224 } else if (rti.baseIntent != null) {
7225 if (pm.queryIntentActivities(rti.baseIntent,
7226 null, 0) == null) {
7227 continue;
7228 }
7229 }
7230 } catch (RemoteException e) {
7231 // Will never happen.
7232 }
7233 }
7234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007235 res.add(rti);
7236 maxNum--;
7237 }
7238 }
7239 return res;
7240 }
7241 }
7242
7243 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
7244 int j;
7245 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
7246 TaskRecord jt = startTask;
7247
7248 // First look backwards
7249 for (j=startIndex-1; j>=0; j--) {
7250 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7251 if (r.task != jt) {
7252 jt = r.task;
7253 if (affinity.equals(jt.affinity)) {
7254 return j;
7255 }
7256 }
7257 }
7258
7259 // Now look forwards
7260 final int N = mHistory.size();
7261 jt = startTask;
7262 for (j=startIndex+1; j<N; j++) {
7263 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7264 if (r.task != jt) {
7265 if (affinity.equals(jt.affinity)) {
7266 return j;
7267 }
7268 jt = r.task;
7269 }
7270 }
7271
7272 // Might it be at the top?
7273 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
7274 return N-1;
7275 }
7276
7277 return -1;
7278 }
7279
7280 /**
7281 * Perform a reset of the given task, if needed as part of launching it.
7282 * Returns the new HistoryRecord at the top of the task.
7283 */
7284 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
7285 HistoryRecord newActivity) {
7286 boolean forceReset = (newActivity.info.flags
7287 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
7288 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
7289 if ((newActivity.info.flags
7290 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
7291 forceReset = true;
7292 }
7293 }
7294
7295 final TaskRecord task = taskTop.task;
7296
7297 // We are going to move through the history list so that we can look
7298 // at each activity 'target' with 'below' either the interesting
7299 // activity immediately below it in the stack or null.
7300 HistoryRecord target = null;
7301 int targetI = 0;
7302 int taskTopI = -1;
7303 int replyChainEnd = -1;
7304 int lastReparentPos = -1;
7305 for (int i=mHistory.size()-1; i>=-1; i--) {
7306 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
7307
7308 if (below != null && below.finishing) {
7309 continue;
7310 }
7311 if (target == null) {
7312 target = below;
7313 targetI = i;
7314 // If we were in the middle of a reply chain before this
7315 // task, it doesn't appear like the root of the chain wants
7316 // anything interesting, so drop it.
7317 replyChainEnd = -1;
7318 continue;
7319 }
7320
7321 final int flags = target.info.flags;
7322
7323 final boolean finishOnTaskLaunch =
7324 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7325 final boolean allowTaskReparenting =
7326 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7327
7328 if (target.task == task) {
7329 // We are inside of the task being reset... we'll either
7330 // finish this activity, push it out for another task,
7331 // or leave it as-is. We only do this
7332 // for activities that are not the root of the task (since
7333 // if we finish the root, we may no longer have the task!).
7334 if (taskTopI < 0) {
7335 taskTopI = targetI;
7336 }
7337 if (below != null && below.task == task) {
7338 final boolean clearWhenTaskReset =
7339 (target.intent.getFlags()
7340 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007341 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007342 // If this activity is sending a reply to a previous
7343 // activity, we can't do anything with it now until
7344 // we reach the start of the reply chain.
7345 // XXX note that we are assuming the result is always
7346 // to the previous activity, which is almost always
7347 // the case but we really shouldn't count on.
7348 if (replyChainEnd < 0) {
7349 replyChainEnd = targetI;
7350 }
Ed Heyl73798232009-03-24 21:32:21 -07007351 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352 && target.taskAffinity != null
7353 && !target.taskAffinity.equals(task.affinity)) {
7354 // If this activity has an affinity for another
7355 // task, then we need to move it out of here. We will
7356 // move it as far out of the way as possible, to the
7357 // bottom of the activity stack. This also keeps it
7358 // correctly ordered with any activities we previously
7359 // moved.
7360 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7361 if (target.taskAffinity != null
7362 && target.taskAffinity.equals(p.task.affinity)) {
7363 // If the activity currently at the bottom has the
7364 // same task affinity as the one we are moving,
7365 // then merge it into the same task.
7366 target.task = p.task;
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 bottom task " + p.task);
7369 } else {
7370 mCurTask++;
7371 if (mCurTask <= 0) {
7372 mCurTask = 1;
7373 }
7374 target.task = new TaskRecord(mCurTask, target.info, null,
7375 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7376 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007377 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 + " out to new task " + target.task);
7379 }
7380 mWindowManager.setAppGroupId(target, task.taskId);
7381 if (replyChainEnd < 0) {
7382 replyChainEnd = targetI;
7383 }
7384 int dstPos = 0;
7385 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7386 p = (HistoryRecord)mHistory.get(srcPos);
7387 if (p.finishing) {
7388 continue;
7389 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007390 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 + " out to target's task " + target.task);
7392 task.numActivities--;
7393 p.task = target.task;
7394 target.task.numActivities++;
7395 mHistory.remove(srcPos);
7396 mHistory.add(dstPos, p);
7397 mWindowManager.moveAppToken(dstPos, p);
7398 mWindowManager.setAppGroupId(p, p.task.taskId);
7399 dstPos++;
7400 if (VALIDATE_TOKENS) {
7401 mWindowManager.validateAppTokens(mHistory);
7402 }
7403 i++;
7404 }
7405 if (taskTop == p) {
7406 taskTop = below;
7407 }
7408 if (taskTopI == replyChainEnd) {
7409 taskTopI = -1;
7410 }
7411 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007412 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007413 } else if (forceReset || finishOnTaskLaunch
7414 || clearWhenTaskReset) {
7415 // If the activity should just be removed -- either
7416 // because it asks for it, or the task should be
7417 // cleared -- then finish it and anything that is
7418 // part of its reply chain.
7419 if (clearWhenTaskReset) {
7420 // In this case, we want to finish this activity
7421 // and everything above it, so be sneaky and pretend
7422 // like these are all in the reply chain.
7423 replyChainEnd = targetI+1;
7424 while (replyChainEnd < mHistory.size() &&
7425 ((HistoryRecord)mHistory.get(
7426 replyChainEnd)).task == task) {
7427 replyChainEnd++;
7428 }
7429 replyChainEnd--;
7430 } else if (replyChainEnd < 0) {
7431 replyChainEnd = targetI;
7432 }
7433 HistoryRecord p = null;
7434 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7435 p = (HistoryRecord)mHistory.get(srcPos);
7436 if (p.finishing) {
7437 continue;
7438 }
7439 if (finishActivityLocked(p, srcPos,
7440 Activity.RESULT_CANCELED, null, "reset")) {
7441 replyChainEnd--;
7442 srcPos--;
7443 }
7444 }
7445 if (taskTop == p) {
7446 taskTop = below;
7447 }
7448 if (taskTopI == replyChainEnd) {
7449 taskTopI = -1;
7450 }
7451 replyChainEnd = -1;
7452 } else {
7453 // If we were in the middle of a chain, well the
7454 // activity that started it all doesn't want anything
7455 // special, so leave it all as-is.
7456 replyChainEnd = -1;
7457 }
7458 } else {
7459 // Reached the bottom of the task -- any reply chain
7460 // should be left as-is.
7461 replyChainEnd = -1;
7462 }
7463
7464 } else if (target.resultTo != null) {
7465 // If this activity is sending a reply to a previous
7466 // activity, we can't do anything with it now until
7467 // we reach the start of the reply chain.
7468 // XXX note that we are assuming the result is always
7469 // to the previous activity, which is almost always
7470 // the case but we really shouldn't count on.
7471 if (replyChainEnd < 0) {
7472 replyChainEnd = targetI;
7473 }
7474
7475 } else if (taskTopI >= 0 && allowTaskReparenting
7476 && task.affinity != null
7477 && task.affinity.equals(target.taskAffinity)) {
7478 // We are inside of another task... if this activity has
7479 // an affinity for our task, then either remove it if we are
7480 // clearing or move it over to our task. Note that
7481 // we currently punt on the case where we are resetting a
7482 // task that is not at the top but who has activities above
7483 // with an affinity to it... this is really not a normal
7484 // case, and we will need to later pull that task to the front
7485 // and usually at that point we will do the reset and pick
7486 // up those remaining activities. (This only happens if
7487 // someone starts an activity in a new task from an activity
7488 // in a task that is not currently on top.)
7489 if (forceReset || finishOnTaskLaunch) {
7490 if (replyChainEnd < 0) {
7491 replyChainEnd = targetI;
7492 }
7493 HistoryRecord p = null;
7494 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7495 p = (HistoryRecord)mHistory.get(srcPos);
7496 if (p.finishing) {
7497 continue;
7498 }
7499 if (finishActivityLocked(p, srcPos,
7500 Activity.RESULT_CANCELED, null, "reset")) {
7501 taskTopI--;
7502 lastReparentPos--;
7503 replyChainEnd--;
7504 srcPos--;
7505 }
7506 }
7507 replyChainEnd = -1;
7508 } else {
7509 if (replyChainEnd < 0) {
7510 replyChainEnd = targetI;
7511 }
7512 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7513 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7514 if (p.finishing) {
7515 continue;
7516 }
7517 if (lastReparentPos < 0) {
7518 lastReparentPos = taskTopI;
7519 taskTop = p;
7520 } else {
7521 lastReparentPos--;
7522 }
7523 mHistory.remove(srcPos);
7524 p.task.numActivities--;
7525 p.task = task;
7526 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007527 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007528 + " in to resetting task " + task);
7529 task.numActivities++;
7530 mWindowManager.moveAppToken(lastReparentPos, p);
7531 mWindowManager.setAppGroupId(p, p.task.taskId);
7532 if (VALIDATE_TOKENS) {
7533 mWindowManager.validateAppTokens(mHistory);
7534 }
7535 }
7536 replyChainEnd = -1;
7537
7538 // Now we've moved it in to place... but what if this is
7539 // a singleTop activity and we have put it on top of another
7540 // instance of the same activity? Then we drop the instance
7541 // below so it remains singleTop.
7542 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7543 for (int j=lastReparentPos-1; j>=0; j--) {
7544 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7545 if (p.finishing) {
7546 continue;
7547 }
7548 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7549 if (finishActivityLocked(p, j,
7550 Activity.RESULT_CANCELED, null, "replace")) {
7551 taskTopI--;
7552 lastReparentPos--;
7553 }
7554 }
7555 }
7556 }
7557 }
7558 }
7559
7560 target = below;
7561 targetI = i;
7562 }
7563
7564 return taskTop;
7565 }
7566
7567 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007568 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569 */
7570 public void moveTaskToFront(int task) {
7571 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7572 "moveTaskToFront()");
7573
7574 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007575 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7576 Binder.getCallingUid(), "Task to front")) {
7577 return;
7578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007579 final long origId = Binder.clearCallingIdentity();
7580 try {
7581 int N = mRecentTasks.size();
7582 for (int i=0; i<N; i++) {
7583 TaskRecord tr = mRecentTasks.get(i);
7584 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007585 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007586 return;
7587 }
7588 }
7589 for (int i=mHistory.size()-1; i>=0; i--) {
7590 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7591 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007592 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007593 return;
7594 }
7595 }
7596 } finally {
7597 Binder.restoreCallingIdentity(origId);
7598 }
7599 }
7600 }
7601
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007602 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007603 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007604
7605 final int task = tr.taskId;
7606 int top = mHistory.size()-1;
7607
7608 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7609 // nothing to do!
7610 return;
7611 }
7612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613 ArrayList moved = new ArrayList();
7614
7615 // Applying the affinities may have removed entries from the history,
7616 // so get the size again.
7617 top = mHistory.size()-1;
7618 int pos = top;
7619
7620 // Shift all activities with this task up to the top
7621 // of the stack, keeping them in the same internal order.
7622 while (pos >= 0) {
7623 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007624 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7626 boolean first = true;
7627 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007628 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007629 mHistory.remove(pos);
7630 mHistory.add(top, r);
7631 moved.add(0, r);
7632 top--;
7633 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007634 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007635 first = false;
7636 }
7637 }
7638 pos--;
7639 }
7640
Joe Onorato8a9b2202010-02-26 18:56:32 -08007641 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007642 "Prepare to front transition: task=" + tr);
7643 if (reason != null &&
7644 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7645 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7646 HistoryRecord r = topRunningActivityLocked(null);
7647 if (r != null) {
7648 mNoAnimActivities.add(r);
7649 }
7650 } else {
7651 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7652 }
7653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007654 mWindowManager.moveAppTokensToTop(moved);
7655 if (VALIDATE_TOKENS) {
7656 mWindowManager.validateAppTokens(mHistory);
7657 }
7658
Josh Bartel7f208742010-02-25 11:01:44 -06007659 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007660 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007661 }
7662
Josh Bartel7f208742010-02-25 11:01:44 -06007663 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007664 resumeTopActivityLocked(null);
7665 }
7666
7667 public void moveTaskToBack(int task) {
7668 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7669 "moveTaskToBack()");
7670
7671 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007672 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7673 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7674 Binder.getCallingUid(), "Task to back")) {
7675 return;
7676 }
7677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007678 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007679 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007680 Binder.restoreCallingIdentity(origId);
7681 }
7682 }
7683
7684 /**
7685 * Moves an activity, and all of the other activities within the same task, to the bottom
7686 * of the history stack. The activity's order within the task is unchanged.
7687 *
7688 * @param token A reference to the activity we wish to move
7689 * @param nonRoot If false then this only works if the activity is the root
7690 * of a task; if true it will work for any activity in a task.
7691 * @return Returns true if the move completed, false if not.
7692 */
7693 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7694 synchronized(this) {
7695 final long origId = Binder.clearCallingIdentity();
7696 int taskId = getTaskForActivityLocked(token, !nonRoot);
7697 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007698 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007699 }
7700 Binder.restoreCallingIdentity(origId);
7701 }
7702 return false;
7703 }
7704
7705 /**
7706 * Worker method for rearranging history stack. Implements the function of moving all
7707 * activities for a specific task (gathering them if disjoint) into a single group at the
7708 * bottom of the stack.
7709 *
7710 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7711 * to premeptively cancel the move.
7712 *
7713 * @param task The taskId to collect and move to the bottom.
7714 * @return Returns true if the move completed, false if not.
7715 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007716 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007717 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718
7719 // If we have a watcher, preflight the move before committing to it. First check
7720 // for *other* available tasks, but if none are available, then try again allowing the
7721 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007722 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007723 HistoryRecord next = topRunningActivityLocked(null, task);
7724 if (next == null) {
7725 next = topRunningActivityLocked(null, 0);
7726 }
7727 if (next != null) {
7728 // ask watcher if this is allowed
7729 boolean moveOK = true;
7730 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007731 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007732 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007733 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007734 }
7735 if (!moveOK) {
7736 return false;
7737 }
7738 }
7739 }
7740
7741 ArrayList moved = new ArrayList();
7742
Joe Onorato8a9b2202010-02-26 18:56:32 -08007743 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007744 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007745
7746 final int N = mHistory.size();
7747 int bottom = 0;
7748 int pos = 0;
7749
7750 // Shift all activities with this task down to the bottom
7751 // of the stack, keeping them in the same internal order.
7752 while (pos < N) {
7753 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007754 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007755 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7756 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007757 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007758 mHistory.remove(pos);
7759 mHistory.add(bottom, r);
7760 moved.add(r);
7761 bottom++;
7762 }
7763 pos++;
7764 }
7765
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007766 if (reason != null &&
7767 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7768 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7769 HistoryRecord r = topRunningActivityLocked(null);
7770 if (r != null) {
7771 mNoAnimActivities.add(r);
7772 }
7773 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007774 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007776 mWindowManager.moveAppTokensToBottom(moved);
7777 if (VALIDATE_TOKENS) {
7778 mWindowManager.validateAppTokens(mHistory);
7779 }
7780
Josh Bartel7f208742010-02-25 11:01:44 -06007781 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 return true;
7783 }
7784
7785 public void moveTaskBackwards(int task) {
7786 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7787 "moveTaskBackwards()");
7788
7789 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007790 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7791 Binder.getCallingUid(), "Task backwards")) {
7792 return;
7793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 final long origId = Binder.clearCallingIdentity();
7795 moveTaskBackwardsLocked(task);
7796 Binder.restoreCallingIdentity(origId);
7797 }
7798 }
7799
7800 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007801 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007802 }
7803
7804 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7805 synchronized(this) {
7806 return getTaskForActivityLocked(token, onlyRoot);
7807 }
7808 }
7809
7810 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7811 final int N = mHistory.size();
7812 TaskRecord lastTask = null;
7813 for (int i=0; i<N; i++) {
7814 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7815 if (r == token) {
7816 if (!onlyRoot || lastTask != r.task) {
7817 return r.task.taskId;
7818 }
7819 return -1;
7820 }
7821 lastTask = r.task;
7822 }
7823
7824 return -1;
7825 }
7826
7827 /**
7828 * Returns the top activity in any existing task matching the given
7829 * Intent. Returns null if no such task is found.
7830 */
7831 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7832 ComponentName cls = intent.getComponent();
7833 if (info.targetActivity != null) {
7834 cls = new ComponentName(info.packageName, info.targetActivity);
7835 }
7836
7837 TaskRecord cp = null;
7838
7839 final int N = mHistory.size();
7840 for (int i=(N-1); i>=0; i--) {
7841 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7842 if (!r.finishing && r.task != cp
7843 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7844 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007845 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007846 // + "/aff=" + r.task.affinity + " to new cls="
7847 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7848 if (r.task.affinity != null) {
7849 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007850 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007851 return r;
7852 }
7853 } else if (r.task.intent != null
7854 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007855 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007856 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007857 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007858 return r;
7859 } else if (r.task.affinityIntent != null
7860 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007861 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007863 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007864 return r;
7865 }
7866 }
7867 }
7868
7869 return null;
7870 }
7871
7872 /**
7873 * Returns the first activity (starting from the top of the stack) that
7874 * is the same as the given activity. Returns null if no such activity
7875 * is found.
7876 */
7877 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7878 ComponentName cls = intent.getComponent();
7879 if (info.targetActivity != null) {
7880 cls = new ComponentName(info.packageName, info.targetActivity);
7881 }
7882
7883 final int N = mHistory.size();
7884 for (int i=(N-1); i>=0; i--) {
7885 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7886 if (!r.finishing) {
7887 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007888 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007889 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007890 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007891 return r;
7892 }
7893 }
7894 }
7895
7896 return null;
7897 }
7898
7899 public void finishOtherInstances(IBinder token, ComponentName className) {
7900 synchronized(this) {
7901 final long origId = Binder.clearCallingIdentity();
7902
7903 int N = mHistory.size();
7904 TaskRecord lastTask = null;
7905 for (int i=0; i<N; i++) {
7906 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7907 if (r.realActivity.equals(className)
7908 && r != token && lastTask != r.task) {
7909 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7910 null, "others")) {
7911 i--;
7912 N--;
7913 }
7914 }
7915 lastTask = r.task;
7916 }
7917
7918 Binder.restoreCallingIdentity(origId);
7919 }
7920 }
7921
7922 // =========================================================
7923 // THUMBNAILS
7924 // =========================================================
7925
7926 public void reportThumbnail(IBinder token,
7927 Bitmap thumbnail, CharSequence description) {
7928 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7929 final long origId = Binder.clearCallingIdentity();
7930 sendPendingThumbnail(null, token, thumbnail, description, true);
7931 Binder.restoreCallingIdentity(origId);
7932 }
7933
7934 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7935 Bitmap thumbnail, CharSequence description, boolean always) {
7936 TaskRecord task = null;
7937 ArrayList receivers = null;
7938
7939 //System.out.println("Send pending thumbnail: " + r);
7940
7941 synchronized(this) {
7942 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007943 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007944 if (index < 0) {
7945 return;
7946 }
7947 r = (HistoryRecord)mHistory.get(index);
7948 }
7949 if (thumbnail == null) {
7950 thumbnail = r.thumbnail;
7951 description = r.description;
7952 }
7953 if (thumbnail == null && !always) {
7954 // If there is no thumbnail, and this entry is not actually
7955 // going away, then abort for now and pick up the next
7956 // thumbnail we get.
7957 return;
7958 }
7959 task = r.task;
7960
7961 int N = mPendingThumbnails.size();
7962 int i=0;
7963 while (i<N) {
7964 PendingThumbnailsRecord pr =
7965 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7966 //System.out.println("Looking in " + pr.pendingRecords);
7967 if (pr.pendingRecords.remove(r)) {
7968 if (receivers == null) {
7969 receivers = new ArrayList();
7970 }
7971 receivers.add(pr);
7972 if (pr.pendingRecords.size() == 0) {
7973 pr.finished = true;
7974 mPendingThumbnails.remove(i);
7975 N--;
7976 continue;
7977 }
7978 }
7979 i++;
7980 }
7981 }
7982
7983 if (receivers != null) {
7984 final int N = receivers.size();
7985 for (int i=0; i<N; i++) {
7986 try {
7987 PendingThumbnailsRecord pr =
7988 (PendingThumbnailsRecord)receivers.get(i);
7989 pr.receiver.newThumbnail(
7990 task != null ? task.taskId : -1, thumbnail, description);
7991 if (pr.finished) {
7992 pr.receiver.finished();
7993 }
7994 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007995 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007996 }
7997 }
7998 }
7999 }
8000
8001 // =========================================================
8002 // CONTENT PROVIDERS
8003 // =========================================================
8004
8005 private final List generateApplicationProvidersLocked(ProcessRecord app) {
8006 List providers = null;
8007 try {
8008 providers = ActivityThread.getPackageManager().
8009 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008010 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008011 } catch (RemoteException ex) {
8012 }
8013 if (providers != null) {
8014 final int N = providers.size();
8015 for (int i=0; i<N; i++) {
8016 ProviderInfo cpi =
8017 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008018 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008019 if (cpr == null) {
8020 cpr = new ContentProviderRecord(cpi, app.info);
8021 mProvidersByClass.put(cpi.name, cpr);
8022 }
8023 app.pubProviders.put(cpi.name, cpr);
8024 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008025 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008026 }
8027 }
8028 return providers;
8029 }
8030
8031 private final String checkContentProviderPermissionLocked(
8032 ProviderInfo cpi, ProcessRecord r, int mode) {
8033 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
8034 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
8035 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
8036 cpi.exported ? -1 : cpi.applicationInfo.uid)
8037 == PackageManager.PERMISSION_GRANTED
8038 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8039 return null;
8040 }
8041 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
8042 cpi.exported ? -1 : cpi.applicationInfo.uid)
8043 == PackageManager.PERMISSION_GRANTED) {
8044 return null;
8045 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07008046
8047 PathPermission[] pps = cpi.pathPermissions;
8048 if (pps != null) {
8049 int i = pps.length;
8050 while (i > 0) {
8051 i--;
8052 PathPermission pp = pps[i];
8053 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
8054 cpi.exported ? -1 : cpi.applicationInfo.uid)
8055 == PackageManager.PERMISSION_GRANTED
8056 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8057 return null;
8058 }
8059 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
8060 cpi.exported ? -1 : cpi.applicationInfo.uid)
8061 == PackageManager.PERMISSION_GRANTED) {
8062 return null;
8063 }
8064 }
8065 }
8066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008067 String msg = "Permission Denial: opening provider " + cpi.name
8068 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
8069 + ", uid=" + callingUid + ") requires "
8070 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008071 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 return msg;
8073 }
8074
8075 private final ContentProviderHolder getContentProviderImpl(
8076 IApplicationThread caller, String name) {
8077 ContentProviderRecord cpr;
8078 ProviderInfo cpi = null;
8079
8080 synchronized(this) {
8081 ProcessRecord r = null;
8082 if (caller != null) {
8083 r = getRecordForAppLocked(caller);
8084 if (r == null) {
8085 throw new SecurityException(
8086 "Unable to find app for caller " + caller
8087 + " (pid=" + Binder.getCallingPid()
8088 + ") when getting content provider " + name);
8089 }
8090 }
8091
8092 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07008093 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008094 if (cpr != null) {
8095 cpi = cpr.info;
8096 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8097 return new ContentProviderHolder(cpi,
8098 cpi.readPermission != null
8099 ? cpi.readPermission : cpi.writePermission);
8100 }
8101
8102 if (r != null && cpr.canRunHere(r)) {
8103 // This provider has been published or is in the process
8104 // of being published... but it is also allowed to run
8105 // in the caller's process, so don't make a connection
8106 // and just let the caller instantiate its own instance.
8107 if (cpr.provider != null) {
8108 // don't give caller the provider object, it needs
8109 // to make its own.
8110 cpr = new ContentProviderRecord(cpr);
8111 }
8112 return cpr;
8113 }
8114
8115 final long origId = Binder.clearCallingIdentity();
8116
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008117 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008118 // return it right away.
8119 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008120 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008121 "Adding provider requested by "
8122 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008123 + cpr.info.processName);
8124 Integer cnt = r.conProviders.get(cpr);
8125 if (cnt == null) {
8126 r.conProviders.put(cpr, new Integer(1));
8127 } else {
8128 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008130 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008131 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
8132 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07008133 // make sure to count it as being accessed and thus
8134 // back up on the LRU list. This is good because
8135 // content providers are often expensive to start.
8136 updateLruProcessLocked(cpr.app, false, true);
8137 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07008138 } else {
8139 cpr.externals++;
8140 }
8141
8142 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008143 updateOomAdjLocked(cpr.app);
8144 }
8145
8146 Binder.restoreCallingIdentity(origId);
8147
8148 } else {
8149 try {
8150 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008151 resolveContentProvider(name,
8152 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008153 } catch (RemoteException ex) {
8154 }
8155 if (cpi == null) {
8156 return null;
8157 }
8158
8159 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8160 return new ContentProviderHolder(cpi,
8161 cpi.readPermission != null
8162 ? cpi.readPermission : cpi.writePermission);
8163 }
8164
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008165 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
8166 && !cpi.processName.equals("system")) {
8167 // If this content provider does not run in the system
8168 // process, and the system is not yet ready to run other
8169 // processes, then fail fast instead of hanging.
8170 throw new IllegalArgumentException(
8171 "Attempt to launch content provider before system ready");
8172 }
8173
Dianne Hackborn860755f2010-06-03 18:47:52 -07008174 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 final boolean firstClass = cpr == null;
8176 if (firstClass) {
8177 try {
8178 ApplicationInfo ai =
8179 ActivityThread.getPackageManager().
8180 getApplicationInfo(
8181 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008182 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008183 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008184 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 + cpi.name);
8186 return null;
8187 }
8188 cpr = new ContentProviderRecord(cpi, ai);
8189 } catch (RemoteException ex) {
8190 // pm is in same process, this will never happen.
8191 }
8192 }
8193
8194 if (r != null && cpr.canRunHere(r)) {
8195 // If this is a multiprocess provider, then just return its
8196 // info and allow the caller to instantiate it. Only do
8197 // this if the provider is the same user as the caller's
8198 // process, or can run as root (so can be in any process).
8199 return cpr;
8200 }
8201
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008202 if (DEBUG_PROVIDER) {
8203 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08008204 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008205 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008206 }
8207
8208 // This is single process, and our app is now connecting to it.
8209 // See if we are already in the process of launching this
8210 // provider.
8211 final int N = mLaunchingProviders.size();
8212 int i;
8213 for (i=0; i<N; i++) {
8214 if (mLaunchingProviders.get(i) == cpr) {
8215 break;
8216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 }
8218
8219 // If the provider is not already being launched, then get it
8220 // started.
8221 if (i >= N) {
8222 final long origId = Binder.clearCallingIdentity();
8223 ProcessRecord proc = startProcessLocked(cpi.processName,
8224 cpr.appInfo, false, 0, "content provider",
8225 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008226 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008227 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008228 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008229 + cpi.applicationInfo.packageName + "/"
8230 + cpi.applicationInfo.uid + " for provider "
8231 + name + ": process is bad");
8232 return null;
8233 }
8234 cpr.launchingApp = proc;
8235 mLaunchingProviders.add(cpr);
8236 Binder.restoreCallingIdentity(origId);
8237 }
8238
8239 // Make sure the provider is published (the same provider class
8240 // may be published under multiple names).
8241 if (firstClass) {
8242 mProvidersByClass.put(cpi.name, cpr);
8243 }
8244 mProvidersByName.put(name, cpr);
8245
8246 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008247 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008248 "Adding provider requested by "
8249 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008250 + cpr.info.processName);
8251 Integer cnt = r.conProviders.get(cpr);
8252 if (cnt == null) {
8253 r.conProviders.put(cpr, new Integer(1));
8254 } else {
8255 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8256 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008257 cpr.clients.add(r);
8258 } else {
8259 cpr.externals++;
8260 }
8261 }
8262 }
8263
8264 // Wait for the provider to be published...
8265 synchronized (cpr) {
8266 while (cpr.provider == null) {
8267 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008268 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008269 + cpi.applicationInfo.packageName + "/"
8270 + cpi.applicationInfo.uid + " for provider "
8271 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008272 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008273 cpi.applicationInfo.packageName,
8274 cpi.applicationInfo.uid, name);
8275 return null;
8276 }
8277 try {
8278 cpr.wait();
8279 } catch (InterruptedException ex) {
8280 }
8281 }
8282 }
8283 return cpr;
8284 }
8285
8286 public final ContentProviderHolder getContentProvider(
8287 IApplicationThread caller, String name) {
8288 if (caller == null) {
8289 String msg = "null IApplicationThread when getting content provider "
8290 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008291 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008292 throw new SecurityException(msg);
8293 }
8294
8295 return getContentProviderImpl(caller, name);
8296 }
8297
8298 private ContentProviderHolder getContentProviderExternal(String name) {
8299 return getContentProviderImpl(null, name);
8300 }
8301
8302 /**
8303 * Drop a content provider from a ProcessRecord's bookkeeping
8304 * @param cpr
8305 */
8306 public void removeContentProvider(IApplicationThread caller, String name) {
8307 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008308 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008309 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008310 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008311 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008312 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008313 return;
8314 }
8315 final ProcessRecord r = getRecordForAppLocked(caller);
8316 if (r == null) {
8317 throw new SecurityException(
8318 "Unable to find app for caller " + caller +
8319 " when removing content provider " + name);
8320 }
8321 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008322 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008323 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008324 + r.info.processName + " from process "
8325 + localCpr.appInfo.processName);
8326 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008327 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008328 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008329 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008330 return;
8331 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008332 Integer cnt = r.conProviders.get(localCpr);
8333 if (cnt == null || cnt.intValue() <= 1) {
8334 localCpr.clients.remove(r);
8335 r.conProviders.remove(localCpr);
8336 } else {
8337 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008339 }
8340 updateOomAdjLocked();
8341 }
8342 }
8343
8344 private void removeContentProviderExternal(String name) {
8345 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008346 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008347 if(cpr == null) {
8348 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008349 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008350 return;
8351 }
8352
8353 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008354 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008355 localCpr.externals--;
8356 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008357 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008358 }
8359 updateOomAdjLocked();
8360 }
8361 }
8362
8363 public final void publishContentProviders(IApplicationThread caller,
8364 List<ContentProviderHolder> providers) {
8365 if (providers == null) {
8366 return;
8367 }
8368
8369 synchronized(this) {
8370 final ProcessRecord r = getRecordForAppLocked(caller);
8371 if (r == null) {
8372 throw new SecurityException(
8373 "Unable to find app for caller " + caller
8374 + " (pid=" + Binder.getCallingPid()
8375 + ") when publishing content providers");
8376 }
8377
8378 final long origId = Binder.clearCallingIdentity();
8379
8380 final int N = providers.size();
8381 for (int i=0; i<N; i++) {
8382 ContentProviderHolder src = providers.get(i);
8383 if (src == null || src.info == null || src.provider == null) {
8384 continue;
8385 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07008386 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008387 if (dst != null) {
8388 mProvidersByClass.put(dst.info.name, dst);
8389 String names[] = dst.info.authority.split(";");
8390 for (int j = 0; j < names.length; j++) {
8391 mProvidersByName.put(names[j], dst);
8392 }
8393
8394 int NL = mLaunchingProviders.size();
8395 int j;
8396 for (j=0; j<NL; j++) {
8397 if (mLaunchingProviders.get(j) == dst) {
8398 mLaunchingProviders.remove(j);
8399 j--;
8400 NL--;
8401 }
8402 }
8403 synchronized (dst) {
8404 dst.provider = src.provider;
8405 dst.app = r;
8406 dst.notifyAll();
8407 }
8408 updateOomAdjLocked(r);
8409 }
8410 }
8411
8412 Binder.restoreCallingIdentity(origId);
8413 }
8414 }
8415
8416 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008417 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008418 synchronized (mSelf) {
8419 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8420 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008421 if (providers != null) {
8422 for (int i=providers.size()-1; i>=0; i--) {
8423 ProviderInfo pi = (ProviderInfo)providers.get(i);
8424 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8425 Slog.w(TAG, "Not installing system proc provider " + pi.name
8426 + ": not system .apk");
8427 providers.remove(i);
8428 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008429 }
8430 }
8431 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008432 if (providers != null) {
8433 mSystemThread.installSystemProviders(providers);
8434 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008435 }
8436
8437 // =========================================================
8438 // GLOBAL MANAGEMENT
8439 // =========================================================
8440
8441 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8442 ApplicationInfo info, String customProcess) {
8443 String proc = customProcess != null ? customProcess : info.processName;
8444 BatteryStatsImpl.Uid.Proc ps = null;
8445 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8446 synchronized (stats) {
8447 ps = stats.getProcessStatsLocked(info.uid, proc);
8448 }
8449 return new ProcessRecord(ps, thread, info, proc);
8450 }
8451
8452 final ProcessRecord addAppLocked(ApplicationInfo info) {
8453 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8454
8455 if (app == null) {
8456 app = newProcessRecordLocked(null, info, null);
8457 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008458 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008459 }
8460
8461 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8462 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8463 app.persistent = true;
8464 app.maxAdj = CORE_SERVER_ADJ;
8465 }
8466 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8467 mPersistentStartingProcesses.add(app);
8468 startProcessLocked(app, "added application", app.processName);
8469 }
8470
8471 return app;
8472 }
8473
8474 public void unhandledBack() {
8475 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8476 "unhandledBack()");
8477
8478 synchronized(this) {
8479 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008480 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008481 TAG, "Performing unhandledBack(): stack size = " + count);
8482 if (count > 1) {
8483 final long origId = Binder.clearCallingIdentity();
8484 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8485 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8486 Binder.restoreCallingIdentity(origId);
8487 }
8488 }
8489 }
8490
8491 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8492 String name = uri.getAuthority();
8493 ContentProviderHolder cph = getContentProviderExternal(name);
8494 ParcelFileDescriptor pfd = null;
8495 if (cph != null) {
8496 // We record the binder invoker's uid in thread-local storage before
8497 // going to the content provider to open the file. Later, in the code
8498 // that handles all permissions checks, we look for this uid and use
8499 // that rather than the Activity Manager's own uid. The effect is that
8500 // we do the check against the caller's permissions even though it looks
8501 // to the content provider like the Activity Manager itself is making
8502 // the request.
8503 sCallerIdentity.set(new Identity(
8504 Binder.getCallingPid(), Binder.getCallingUid()));
8505 try {
8506 pfd = cph.provider.openFile(uri, "r");
8507 } catch (FileNotFoundException e) {
8508 // do nothing; pfd will be returned null
8509 } finally {
8510 // Ensure that whatever happens, we clean up the identity state
8511 sCallerIdentity.remove();
8512 }
8513
8514 // We've got the fd now, so we're done with the provider.
8515 removeContentProviderExternal(name);
8516 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008517 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518 }
8519 return pfd;
8520 }
8521
8522 public void goingToSleep() {
8523 synchronized(this) {
8524 mSleeping = true;
8525 mWindowManager.setEventDispatching(false);
8526
8527 if (mResumedActivity != null) {
8528 pauseIfSleepingLocked();
8529 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008530 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008531 }
8532 }
8533 }
8534
Dianne Hackborn55280a92009-05-07 15:53:46 -07008535 public boolean shutdown(int timeout) {
8536 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8537 != PackageManager.PERMISSION_GRANTED) {
8538 throw new SecurityException("Requires permission "
8539 + android.Manifest.permission.SHUTDOWN);
8540 }
8541
8542 boolean timedout = false;
8543
8544 synchronized(this) {
8545 mShuttingDown = true;
8546 mWindowManager.setEventDispatching(false);
8547
8548 if (mResumedActivity != null) {
8549 pauseIfSleepingLocked();
8550 final long endTime = System.currentTimeMillis() + timeout;
8551 while (mResumedActivity != null || mPausingActivity != null) {
8552 long delay = endTime - System.currentTimeMillis();
8553 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008554 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008555 timedout = true;
8556 break;
8557 }
8558 try {
8559 this.wait();
8560 } catch (InterruptedException e) {
8561 }
8562 }
8563 }
8564 }
8565
8566 mUsageStatsService.shutdown();
8567 mBatteryStatsService.shutdown();
8568
8569 return timedout;
8570 }
8571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008572 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008573 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008574 if (!mGoingToSleep.isHeld()) {
8575 mGoingToSleep.acquire();
8576 if (mLaunchingActivity.isHeld()) {
8577 mLaunchingActivity.release();
8578 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8579 }
8580 }
8581
8582 // If we are not currently pausing an activity, get the current
8583 // one to pause. If we are pausing one, we will just let that stuff
8584 // run and release the wake lock when all done.
8585 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008586 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8587 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008588 startPausingLocked(false, true);
8589 }
8590 }
8591 }
8592
8593 public void wakingUp() {
8594 synchronized(this) {
8595 if (mGoingToSleep.isHeld()) {
8596 mGoingToSleep.release();
8597 }
8598 mWindowManager.setEventDispatching(true);
8599 mSleeping = false;
8600 resumeTopActivityLocked(null);
8601 }
8602 }
8603
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008604 public void stopAppSwitches() {
8605 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8606 != PackageManager.PERMISSION_GRANTED) {
8607 throw new SecurityException("Requires permission "
8608 + android.Manifest.permission.STOP_APP_SWITCHES);
8609 }
8610
8611 synchronized(this) {
8612 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8613 + APP_SWITCH_DELAY_TIME;
8614 mDidAppSwitch = false;
8615 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8616 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8617 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8618 }
8619 }
8620
8621 public void resumeAppSwitches() {
8622 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8623 != PackageManager.PERMISSION_GRANTED) {
8624 throw new SecurityException("Requires permission "
8625 + android.Manifest.permission.STOP_APP_SWITCHES);
8626 }
8627
8628 synchronized(this) {
8629 // Note that we don't execute any pending app switches... we will
8630 // let those wait until either the timeout, or the next start
8631 // activity request.
8632 mAppSwitchesAllowedTime = 0;
8633 }
8634 }
8635
8636 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8637 String name) {
8638 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8639 return true;
8640 }
8641
8642 final int perm = checkComponentPermission(
8643 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8644 callingUid, -1);
8645 if (perm == PackageManager.PERMISSION_GRANTED) {
8646 return true;
8647 }
8648
Joe Onorato8a9b2202010-02-26 18:56:32 -08008649 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008650 return false;
8651 }
8652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008653 public void setDebugApp(String packageName, boolean waitForDebugger,
8654 boolean persistent) {
8655 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8656 "setDebugApp()");
8657
8658 // Note that this is not really thread safe if there are multiple
8659 // callers into it at the same time, but that's not a situation we
8660 // care about.
8661 if (persistent) {
8662 final ContentResolver resolver = mContext.getContentResolver();
8663 Settings.System.putString(
8664 resolver, Settings.System.DEBUG_APP,
8665 packageName);
8666 Settings.System.putInt(
8667 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8668 waitForDebugger ? 1 : 0);
8669 }
8670
8671 synchronized (this) {
8672 if (!persistent) {
8673 mOrigDebugApp = mDebugApp;
8674 mOrigWaitForDebugger = mWaitForDebugger;
8675 }
8676 mDebugApp = packageName;
8677 mWaitForDebugger = waitForDebugger;
8678 mDebugTransient = !persistent;
8679 if (packageName != null) {
8680 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008681 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008682 Binder.restoreCallingIdentity(origId);
8683 }
8684 }
8685 }
8686
8687 public void setAlwaysFinish(boolean enabled) {
8688 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8689 "setAlwaysFinish()");
8690
8691 Settings.System.putInt(
8692 mContext.getContentResolver(),
8693 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8694
8695 synchronized (this) {
8696 mAlwaysFinishActivities = enabled;
8697 }
8698 }
8699
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008700 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008701 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008702 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008703 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008704 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008705 }
8706 }
8707
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008708 public boolean isUserAMonkey() {
8709 // For now the fact that there is a controller implies
8710 // we have a monkey.
8711 synchronized (this) {
8712 return mController != null;
8713 }
8714 }
8715
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008716 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008717 synchronized (this) {
8718 mWatchers.register(watcher);
8719 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008720 }
8721
8722 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008723 synchronized (this) {
8724 mWatchers.unregister(watcher);
8725 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008726 }
8727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008728 public final void enterSafeMode() {
8729 synchronized(this) {
8730 // It only makes sense to do this before the system is ready
8731 // and started launching other packages.
8732 if (!mSystemReady) {
8733 try {
8734 ActivityThread.getPackageManager().enterSafeMode();
8735 } catch (RemoteException e) {
8736 }
8737
8738 View v = LayoutInflater.from(mContext).inflate(
8739 com.android.internal.R.layout.safe_mode, null);
8740 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8741 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8742 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8743 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8744 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8745 lp.format = v.getBackground().getOpacity();
8746 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8747 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8748 ((WindowManager)mContext.getSystemService(
8749 Context.WINDOW_SERVICE)).addView(v, lp);
8750 }
8751 }
8752 }
8753
8754 public void noteWakeupAlarm(IIntentSender sender) {
8755 if (!(sender instanceof PendingIntentRecord)) {
8756 return;
8757 }
8758 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8759 synchronized (stats) {
8760 if (mBatteryStatsService.isOnBattery()) {
8761 mBatteryStatsService.enforceCallingPermission();
8762 PendingIntentRecord rec = (PendingIntentRecord)sender;
8763 int MY_UID = Binder.getCallingUid();
8764 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8765 BatteryStatsImpl.Uid.Pkg pkg =
8766 stats.getPackageStatsLocked(uid, rec.key.packageName);
8767 pkg.incWakeupsLocked();
8768 }
8769 }
8770 }
8771
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008772 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008773 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008774 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008775 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008776 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008777 // XXX Note: don't acquire main activity lock here, because the window
8778 // manager calls in with its locks held.
8779
8780 boolean killed = false;
8781 synchronized (mPidsSelfLocked) {
8782 int[] types = new int[pids.length];
8783 int worstType = 0;
8784 for (int i=0; i<pids.length; i++) {
8785 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8786 if (proc != null) {
8787 int type = proc.setAdj;
8788 types[i] = type;
8789 if (type > worstType) {
8790 worstType = type;
8791 }
8792 }
8793 }
8794
8795 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8796 // then constrain it so we will kill all hidden procs.
8797 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8798 worstType = HIDDEN_APP_MIN_ADJ;
8799 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008800 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 for (int i=0; i<pids.length; i++) {
8802 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8803 if (proc == null) {
8804 continue;
8805 }
8806 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008807 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008808 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008809 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8810 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008811 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008812 proc.killedBackground = true;
8813 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008814 }
8815 }
8816 }
8817 return killed;
8818 }
8819
8820 public void reportPss(IApplicationThread caller, int pss) {
8821 Watchdog.PssRequestor req;
8822 String name;
8823 ProcessRecord callerApp;
8824 synchronized (this) {
8825 if (caller == null) {
8826 return;
8827 }
8828 callerApp = getRecordForAppLocked(caller);
8829 if (callerApp == null) {
8830 return;
8831 }
8832 callerApp.lastPss = pss;
8833 req = callerApp;
8834 name = callerApp.processName;
8835 }
8836 Watchdog.getInstance().reportPss(req, name, pss);
8837 if (!callerApp.persistent) {
8838 removeRequestedPss(callerApp);
8839 }
8840 }
8841
8842 public void requestPss(Runnable completeCallback) {
8843 ArrayList<ProcessRecord> procs;
8844 synchronized (this) {
8845 mRequestPssCallback = completeCallback;
8846 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008847 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8848 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008849 if (!proc.persistent) {
8850 mRequestPssList.add(proc);
8851 }
8852 }
8853 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8854 }
8855
8856 int oldPri = Process.getThreadPriority(Process.myTid());
8857 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8858 for (int i=procs.size()-1; i>=0; i--) {
8859 ProcessRecord proc = procs.get(i);
8860 proc.lastPss = 0;
8861 proc.requestPss();
8862 }
8863 Process.setThreadPriority(oldPri);
8864 }
8865
8866 void removeRequestedPss(ProcessRecord proc) {
8867 Runnable callback = null;
8868 synchronized (this) {
8869 if (mRequestPssList.remove(proc)) {
8870 if (mRequestPssList.size() == 0) {
8871 callback = mRequestPssCallback;
8872 mRequestPssCallback = null;
8873 }
8874 }
8875 }
8876
8877 if (callback != null) {
8878 callback.run();
8879 }
8880 }
8881
8882 public void collectPss(Watchdog.PssStats stats) {
8883 stats.mEmptyPss = 0;
8884 stats.mEmptyCount = 0;
8885 stats.mBackgroundPss = 0;
8886 stats.mBackgroundCount = 0;
8887 stats.mServicePss = 0;
8888 stats.mServiceCount = 0;
8889 stats.mVisiblePss = 0;
8890 stats.mVisibleCount = 0;
8891 stats.mForegroundPss = 0;
8892 stats.mForegroundCount = 0;
8893 stats.mNoPssCount = 0;
8894 synchronized (this) {
8895 int i;
8896 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8897 ? mProcDeaths.length : stats.mProcDeaths.length;
8898 int aggr = 0;
8899 for (i=0; i<NPD; i++) {
8900 aggr += mProcDeaths[i];
8901 stats.mProcDeaths[i] = aggr;
8902 }
8903 while (i<stats.mProcDeaths.length) {
8904 stats.mProcDeaths[i] = 0;
8905 i++;
8906 }
8907
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008908 for (i=mLruProcesses.size()-1; i>=0; i--) {
8909 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008910 if (proc.persistent) {
8911 continue;
8912 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008913 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008914 if (proc.lastPss == 0) {
8915 stats.mNoPssCount++;
8916 continue;
8917 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008918 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8919 if (proc.empty) {
8920 stats.mEmptyPss += proc.lastPss;
8921 stats.mEmptyCount++;
8922 } else {
8923 stats.mBackgroundPss += proc.lastPss;
8924 stats.mBackgroundCount++;
8925 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008926 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8927 stats.mVisiblePss += proc.lastPss;
8928 stats.mVisibleCount++;
8929 } else {
8930 stats.mForegroundPss += proc.lastPss;
8931 stats.mForegroundCount++;
8932 }
8933 }
8934 }
8935 }
8936
8937 public final void startRunning(String pkg, String cls, String action,
8938 String data) {
8939 synchronized(this) {
8940 if (mStartRunning) {
8941 return;
8942 }
8943 mStartRunning = true;
8944 mTopComponent = pkg != null && cls != null
8945 ? new ComponentName(pkg, cls) : null;
8946 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8947 mTopData = data;
8948 if (!mSystemReady) {
8949 return;
8950 }
8951 }
8952
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008953 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008954 }
8955
8956 private void retrieveSettings() {
8957 final ContentResolver resolver = mContext.getContentResolver();
8958 String debugApp = Settings.System.getString(
8959 resolver, Settings.System.DEBUG_APP);
8960 boolean waitForDebugger = Settings.System.getInt(
8961 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8962 boolean alwaysFinishActivities = Settings.System.getInt(
8963 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8964
8965 Configuration configuration = new Configuration();
8966 Settings.System.getConfiguration(resolver, configuration);
8967
8968 synchronized (this) {
8969 mDebugApp = mOrigDebugApp = debugApp;
8970 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8971 mAlwaysFinishActivities = alwaysFinishActivities;
8972 // This happens before any activities are started, so we can
8973 // change mConfiguration in-place.
8974 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008975 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008976 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008977 }
8978 }
8979
8980 public boolean testIsSystemReady() {
8981 // no need to synchronize(this) just to read & return the value
8982 return mSystemReady;
8983 }
8984
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008985 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008986 // In the simulator, startRunning will never have been called, which
8987 // normally sets a few crucial variables. Do it here instead.
8988 if (!Process.supportsProcesses()) {
8989 mStartRunning = true;
8990 mTopAction = Intent.ACTION_MAIN;
8991 }
8992
8993 synchronized(this) {
8994 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008995 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008996 return;
8997 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008998
8999 // Check to see if there are any update receivers to run.
9000 if (!mDidUpdate) {
9001 if (mWaitingUpdate) {
9002 return;
9003 }
9004 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
9005 List<ResolveInfo> ris = null;
9006 try {
9007 ris = ActivityThread.getPackageManager().queryIntentReceivers(
9008 intent, null, 0);
9009 } catch (RemoteException e) {
9010 }
9011 if (ris != null) {
9012 for (int i=ris.size()-1; i>=0; i--) {
9013 if ((ris.get(i).activityInfo.applicationInfo.flags
9014 &ApplicationInfo.FLAG_SYSTEM) == 0) {
9015 ris.remove(i);
9016 }
9017 }
9018 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
9019 for (int i=0; i<ris.size(); i++) {
9020 ActivityInfo ai = ris.get(i).activityInfo;
9021 intent.setComponent(new ComponentName(ai.packageName, ai.name));
9022 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08009023 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009024 finisher = new IIntentReceiver.Stub() {
9025 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07009026 String data, Bundle extras, boolean ordered,
9027 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009028 throws RemoteException {
9029 synchronized (ActivityManagerService.this) {
9030 mDidUpdate = true;
9031 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009032 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009033 }
9034 };
9035 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009036 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009037 broadcastIntentLocked(null, null, intent, null, finisher,
9038 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08009039 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009040 mWaitingUpdate = true;
9041 }
9042 }
9043 }
9044 if (mWaitingUpdate) {
9045 return;
9046 }
9047 mDidUpdate = true;
9048 }
9049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009050 mSystemReady = true;
9051 if (!mStartRunning) {
9052 return;
9053 }
9054 }
9055
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009056 ArrayList<ProcessRecord> procsToKill = null;
9057 synchronized(mPidsSelfLocked) {
9058 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
9059 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
9060 if (!isAllowedWhileBooting(proc.info)){
9061 if (procsToKill == null) {
9062 procsToKill = new ArrayList<ProcessRecord>();
9063 }
9064 procsToKill.add(proc);
9065 }
9066 }
9067 }
9068
9069 if (procsToKill != null) {
9070 synchronized(this) {
9071 for (int i=procsToKill.size()-1; i>=0; i--) {
9072 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009073 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009074 removeProcessLocked(proc, true);
9075 }
9076 }
9077 }
9078
Joe Onorato8a9b2202010-02-26 18:56:32 -08009079 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009080 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 SystemClock.uptimeMillis());
9082
9083 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009084 // Make sure we have no pre-ready processes sitting around.
9085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009086 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
9087 ResolveInfo ri = mContext.getPackageManager()
9088 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07009089 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009090 CharSequence errorMsg = null;
9091 if (ri != null) {
9092 ActivityInfo ai = ri.activityInfo;
9093 ApplicationInfo app = ai.applicationInfo;
9094 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
9095 mTopAction = Intent.ACTION_FACTORY_TEST;
9096 mTopData = null;
9097 mTopComponent = new ComponentName(app.packageName,
9098 ai.name);
9099 } else {
9100 errorMsg = mContext.getResources().getText(
9101 com.android.internal.R.string.factorytest_not_system);
9102 }
9103 } else {
9104 errorMsg = mContext.getResources().getText(
9105 com.android.internal.R.string.factorytest_no_action);
9106 }
9107 if (errorMsg != null) {
9108 mTopAction = null;
9109 mTopData = null;
9110 mTopComponent = null;
9111 Message msg = Message.obtain();
9112 msg.what = SHOW_FACTORY_ERROR_MSG;
9113 msg.getData().putCharSequence("msg", errorMsg);
9114 mHandler.sendMessage(msg);
9115 }
9116 }
9117 }
9118
9119 retrieveSettings();
9120
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009121 if (goingCallback != null) goingCallback.run();
9122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009123 synchronized (this) {
9124 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
9125 try {
9126 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009127 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009128 if (apps != null) {
9129 int N = apps.size();
9130 int i;
9131 for (i=0; i<N; i++) {
9132 ApplicationInfo info
9133 = (ApplicationInfo)apps.get(i);
9134 if (info != null &&
9135 !info.packageName.equals("android")) {
9136 addAppLocked(info);
9137 }
9138 }
9139 }
9140 } catch (RemoteException ex) {
9141 // pm is in same process, this will never happen.
9142 }
9143 }
9144
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009145 // Start up initial activity.
9146 mBooting = true;
9147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009148 try {
9149 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
9150 Message msg = Message.obtain();
9151 msg.what = SHOW_UID_ERROR_MSG;
9152 mHandler.sendMessage(msg);
9153 }
9154 } catch (RemoteException e) {
9155 }
9156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009157 resumeTopActivityLocked(null);
9158 }
9159 }
9160
Dan Egnorb7f03672009-12-09 16:22:32 -08009161 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009162 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009163 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009164 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009165 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009166 startAppProblemLocked(app);
9167 app.stopFreezingAllLocked();
9168 return handleAppCrashLocked(app);
9169 }
9170
Dan Egnorb7f03672009-12-09 16:22:32 -08009171 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009172 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009174 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009175 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
9176 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 startAppProblemLocked(app);
9178 app.stopFreezingAllLocked();
9179 }
9180
9181 /**
9182 * Generate a process error record, suitable for attachment to a ProcessRecord.
9183 *
9184 * @param app The ProcessRecord in which the error occurred.
9185 * @param condition Crashing, Application Not Responding, etc. Values are defined in
9186 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08009187 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009188 * @param shortMsg Short message describing the crash.
9189 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08009190 * @param stackTrace Full crash stack trace, may be null.
9191 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009192 * @return Returns a fully-formed AppErrorStateInfo record.
9193 */
9194 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009195 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009196 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08009197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009198 report.condition = condition;
9199 report.processName = app.processName;
9200 report.pid = app.pid;
9201 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08009202 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009203 report.shortMsg = shortMsg;
9204 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08009205 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009206
9207 return report;
9208 }
9209
Dan Egnor42471dd2010-01-07 17:25:22 -08009210 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009211 synchronized (this) {
9212 app.crashing = false;
9213 app.crashingReport = null;
9214 app.notResponding = false;
9215 app.notRespondingReport = null;
9216 if (app.anrDialog == fromDialog) {
9217 app.anrDialog = null;
9218 }
9219 if (app.waitDialog == fromDialog) {
9220 app.waitDialog = null;
9221 }
9222 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009223 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07009224 Slog.i(ActivityManagerService.TAG, "Killing "
9225 + app.processName + " (pid=" + app.pid + "): user's request");
9226 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
9227 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009228 Process.killProcess(app.pid);
9229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009230 }
9231 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009232
Dan Egnorb7f03672009-12-09 16:22:32 -08009233 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009234 long now = SystemClock.uptimeMillis();
9235
9236 Long crashTime = mProcessCrashTimes.get(app.info.processName,
9237 app.info.uid);
9238 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
9239 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08009240 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009241 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009242 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009243 app.info.processName, app.info.uid);
9244 killServicesLocked(app, false);
9245 for (int i=mHistory.size()-1; i>=0; i--) {
9246 HistoryRecord r = (HistoryRecord)mHistory.get(i);
9247 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009248 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009249 + r.intent.getComponent().flattenToShortString());
9250 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
9251 }
9252 }
9253 if (!app.persistent) {
9254 // We don't want to start this process again until the user
9255 // explicitly does so... but for persistent process, we really
9256 // need to keep it running. If a persistent process is actually
9257 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08009258 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009259 app.info.processName);
9260 mBadProcesses.put(app.info.processName, app.info.uid, now);
9261 app.bad = true;
9262 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
9263 app.removed = true;
9264 removeProcessLocked(app, false);
9265 return false;
9266 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009267 } else {
9268 HistoryRecord r = topRunningActivityLocked(null);
9269 if (r.app == app) {
9270 // If the top running activity is from this crashing
9271 // process, then terminate it to avoid getting in a loop.
9272 Slog.w(TAG, " Force finishing activity "
9273 + r.intent.getComponent().flattenToShortString());
9274 int index = indexOfTokenLocked(r);
9275 finishActivityLocked(r, index,
9276 Activity.RESULT_CANCELED, null, "crashed");
9277 // Also terminate an activities below it that aren't yet
9278 // stopped, to avoid a situation where one will get
9279 // re-start our crashing activity once it gets resumed again.
9280 index--;
9281 if (index >= 0) {
9282 r = (HistoryRecord)mHistory.get(index);
9283 if (r.state == ActivityState.RESUMED
9284 || r.state == ActivityState.PAUSING
9285 || r.state == ActivityState.PAUSED) {
9286 if (!r.isHomeActivity) {
9287 Slog.w(TAG, " Force finishing activity "
9288 + r.intent.getComponent().flattenToShortString());
9289 finishActivityLocked(r, index,
9290 Activity.RESULT_CANCELED, null, "crashed");
9291 }
9292 }
9293 }
9294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 }
9296
9297 // Bump up the crash count of any services currently running in the proc.
9298 if (app.services.size() != 0) {
9299 // Any services running in the application need to be placed
9300 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009301 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009302 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009303 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009304 sr.crashCount++;
9305 }
9306 }
9307
9308 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
9309 return true;
9310 }
9311
9312 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009313 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9314 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009315 skipCurrentReceiverLocked(app);
9316 }
9317
9318 void skipCurrentReceiverLocked(ProcessRecord app) {
9319 boolean reschedule = false;
9320 BroadcastRecord r = app.curReceiver;
9321 if (r != null) {
9322 // The current broadcast is waiting for this app's receiver
9323 // to be finished. Looks like that's not going to happen, so
9324 // let the broadcast continue.
9325 logBroadcastReceiverDiscard(r);
9326 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9327 r.resultExtras, r.resultAbort, true);
9328 reschedule = true;
9329 }
9330 r = mPendingBroadcast;
9331 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009332 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009333 "skip & discard pending app " + r);
9334 logBroadcastReceiverDiscard(r);
9335 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9336 r.resultExtras, r.resultAbort, true);
9337 reschedule = true;
9338 }
9339 if (reschedule) {
9340 scheduleBroadcastsLocked();
9341 }
9342 }
9343
Dan Egnor60d87622009-12-16 16:32:58 -08009344 /**
9345 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9346 * The application process will exit immediately after this call returns.
9347 * @param app object of the crashing app, null for the system server
9348 * @param crashInfo describing the exception
9349 */
9350 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9351 ProcessRecord r = findAppProcess(app);
9352
9353 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9354 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009355 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009356 crashInfo.exceptionClassName,
9357 crashInfo.exceptionMessage,
9358 crashInfo.throwFileName,
9359 crashInfo.throwLineNumber);
9360
Dan Egnor42471dd2010-01-07 17:25:22 -08009361 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009362
9363 crashApplication(r, crashInfo);
9364 }
9365
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009366 public void handleApplicationStrictModeViolation(
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009367 IBinder app, int violationMask, ApplicationErrorReport.CrashInfo crashInfo) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009368 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009369
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009370 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009371 Integer stackFingerprint = crashInfo.stackTrace.hashCode();
9372 boolean logIt = true;
9373 synchronized (mAlreadyLoggedViolatedStacks) {
9374 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
9375 logIt = false;
9376 // TODO: sub-sample into EventLog for these, with
9377 // the crashInfo.durationMillis? Then we'd get
9378 // the relative pain numbers, without logging all
9379 // the stack traces repeatedly. We'd want to do
9380 // likewise in the client code, which also does
9381 // dup suppression, before the Binder call.
9382 } else {
9383 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
9384 mAlreadyLoggedViolatedStacks.clear();
9385 }
9386 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
9387 }
9388 }
9389 if (logIt) {
9390 addErrorToDropBox("strictmode", r, null, null, null, null, null, crashInfo);
9391 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009392 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009393
9394 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
9395 AppErrorResult result = new AppErrorResult();
9396 synchronized (this) {
9397 final long origId = Binder.clearCallingIdentity();
9398
9399 Message msg = Message.obtain();
9400 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
9401 HashMap<String, Object> data = new HashMap<String, Object>();
9402 data.put("result", result);
9403 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009404 data.put("violationMask", violationMask);
9405 data.put("crashInfo", crashInfo);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009406 msg.obj = data;
9407 mHandler.sendMessage(msg);
9408
9409 Binder.restoreCallingIdentity(origId);
9410 }
9411 int res = result.get();
9412 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
9413 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009414 }
9415
Dan Egnor60d87622009-12-16 16:32:58 -08009416 /**
9417 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9418 * @param app object of the crashing app, null for the system server
9419 * @param tag reported by the caller
9420 * @param crashInfo describing the context of the error
9421 * @return true if the process should exit immediately (WTF is fatal)
9422 */
9423 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009424 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009425 ProcessRecord r = findAppProcess(app);
9426
9427 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9428 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009429 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009430 tag, crashInfo.exceptionMessage);
9431
Dan Egnor42471dd2010-01-07 17:25:22 -08009432 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009433
Doug Zongker43866e02010-01-07 12:09:54 -08009434 if (Settings.Secure.getInt(mContext.getContentResolver(),
9435 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009436 crashApplication(r, crashInfo);
9437 return true;
9438 } else {
9439 return false;
9440 }
9441 }
9442
9443 /**
9444 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9445 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9446 */
9447 private ProcessRecord findAppProcess(IBinder app) {
9448 if (app == null) {
9449 return null;
9450 }
9451
9452 synchronized (this) {
9453 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9454 final int NA = apps.size();
9455 for (int ia=0; ia<NA; ia++) {
9456 ProcessRecord p = apps.valueAt(ia);
9457 if (p.thread != null && p.thread.asBinder() == app) {
9458 return p;
9459 }
9460 }
9461 }
9462
Joe Onorato8a9b2202010-02-26 18:56:32 -08009463 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009464 return null;
9465 }
9466 }
9467
9468 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009469 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009470 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009471 * @param process which caused the error, null means the system server
9472 * @param activity which triggered the error, null if unknown
9473 * @param parent activity related to the error, null if unknown
9474 * @param subject line related to the error, null if absent
9475 * @param report in long form describing the error, null if absent
9476 * @param logFile to include in the report, null if none
9477 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009478 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009479 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009480 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9481 final String report, final File logFile,
9482 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009483 // NOTE -- this must never acquire the ActivityManagerService lock,
9484 // otherwise the watchdog may be prevented from resetting the system.
9485
Dan Egnora455d192010-03-12 08:52:28 -08009486 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009487 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009488 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009489 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009490 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009491 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009492 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009493 }
9494
Dan Egnora455d192010-03-12 08:52:28 -08009495 final String dropboxTag = prefix + eventType;
9496 final DropBoxManager dbox = (DropBoxManager)
9497 mContext.getSystemService(Context.DROPBOX_SERVICE);
9498
9499 // Exit early if the dropbox isn't configured to accept this report type.
9500 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9501
9502 final StringBuilder sb = new StringBuilder(1024);
9503 if (process == null || process.pid == MY_PID) {
9504 sb.append("Process: system_server\n");
9505 } else {
9506 sb.append("Process: ").append(process.processName).append("\n");
9507 }
9508 if (process != null) {
9509 int flags = process.info.flags;
9510 IPackageManager pm = ActivityThread.getPackageManager();
9511 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9512 for (String pkg : process.pkgList) {
9513 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009514 try {
Dan Egnora455d192010-03-12 08:52:28 -08009515 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9516 if (pi != null) {
9517 sb.append(" v").append(pi.versionCode);
9518 if (pi.versionName != null) {
9519 sb.append(" (").append(pi.versionName).append(")");
9520 }
9521 }
9522 } catch (RemoteException e) {
9523 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009524 }
Dan Egnora455d192010-03-12 08:52:28 -08009525 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009526 }
Dan Egnora455d192010-03-12 08:52:28 -08009527 }
9528 if (activity != null) {
9529 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9530 }
9531 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9532 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9533 }
9534 if (parent != null && parent != activity) {
9535 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9536 }
9537 if (subject != null) {
9538 sb.append("Subject: ").append(subject).append("\n");
9539 }
9540 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009541 if (crashInfo.durationMillis != -1) {
9542 sb.append("Duration-Millis: ").append(crashInfo.durationMillis).append("\n");
9543 }
Dan Egnora455d192010-03-12 08:52:28 -08009544 sb.append("\n");
9545
9546 // Do the rest in a worker thread to avoid blocking the caller on I/O
9547 // (After this point, we shouldn't access AMS internal data structures.)
9548 Thread worker = new Thread("Error dump: " + dropboxTag) {
9549 @Override
9550 public void run() {
9551 if (report != null) {
9552 sb.append(report);
9553 }
9554 if (logFile != null) {
9555 try {
9556 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9557 } catch (IOException e) {
9558 Slog.e(TAG, "Error reading " + logFile, e);
9559 }
9560 }
9561 if (crashInfo != null && crashInfo.stackTrace != null) {
9562 sb.append(crashInfo.stackTrace);
9563 }
9564
9565 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9566 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9567 if (lines > 0) {
9568 sb.append("\n");
9569
9570 // Merge several logcat streams, and take the last N lines
9571 InputStreamReader input = null;
9572 try {
9573 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9574 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9575 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9576
9577 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9578 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9579 input = new InputStreamReader(logcat.getInputStream());
9580
9581 int num;
9582 char[] buf = new char[8192];
9583 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9584 } catch (IOException e) {
9585 Slog.e(TAG, "Error running logcat", e);
9586 } finally {
9587 if (input != null) try { input.close(); } catch (IOException e) {}
9588 }
9589 }
9590
9591 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009592 }
Dan Egnora455d192010-03-12 08:52:28 -08009593 };
9594
9595 if (process == null || process.pid == MY_PID) {
9596 worker.run(); // We may be about to die -- need to run this synchronously
9597 } else {
9598 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009599 }
9600 }
9601
9602 /**
9603 * Bring up the "unexpected error" dialog box for a crashing app.
9604 * Deal with edge cases (intercepts from instrumented applications,
9605 * ActivityController, error intent receivers, that sort of thing).
9606 * @param r the application crashing
9607 * @param crashInfo describing the failure
9608 */
9609 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009610 long timeMillis = System.currentTimeMillis();
9611 String shortMsg = crashInfo.exceptionClassName;
9612 String longMsg = crashInfo.exceptionMessage;
9613 String stackTrace = crashInfo.stackTrace;
9614 if (shortMsg != null && longMsg != null) {
9615 longMsg = shortMsg + ": " + longMsg;
9616 } else if (shortMsg != null) {
9617 longMsg = shortMsg;
9618 }
9619
Dan Egnor60d87622009-12-16 16:32:58 -08009620 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009621 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009622 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009623 try {
9624 String name = r != null ? r.processName : null;
9625 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009626 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009627 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009628 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009629 + " at watcher's request");
9630 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009631 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009632 }
9633 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009634 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009635 }
9636 }
9637
9638 final long origId = Binder.clearCallingIdentity();
9639
9640 // If this process is running instrumentation, finish it.
9641 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009642 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009644 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9645 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009646 Bundle info = new Bundle();
9647 info.putString("shortMsg", shortMsg);
9648 info.putString("longMsg", longMsg);
9649 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9650 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009651 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652 }
9653
Dan Egnor60d87622009-12-16 16:32:58 -08009654 // If we can't identify the process or it's already exceeded its crash quota,
9655 // quit right away without showing a crash dialog.
9656 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009657 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009658 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009659 }
9660
9661 Message msg = Message.obtain();
9662 msg.what = SHOW_ERROR_MSG;
9663 HashMap data = new HashMap();
9664 data.put("result", result);
9665 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009666 msg.obj = data;
9667 mHandler.sendMessage(msg);
9668
9669 Binder.restoreCallingIdentity(origId);
9670 }
9671
9672 int res = result.get();
9673
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009674 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009675 synchronized (this) {
9676 if (r != null) {
9677 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9678 SystemClock.uptimeMillis());
9679 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009680 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009681 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009682 }
9683 }
9684
9685 if (appErrorIntent != null) {
9686 try {
9687 mContext.startActivity(appErrorIntent);
9688 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009689 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009691 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009693
9694 Intent createAppErrorIntentLocked(ProcessRecord r,
9695 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9696 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009697 if (report == null) {
9698 return null;
9699 }
9700 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9701 result.setComponent(r.errorReportReceiver);
9702 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9703 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9704 return result;
9705 }
9706
Dan Egnorb7f03672009-12-09 16:22:32 -08009707 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9708 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009709 if (r.errorReportReceiver == null) {
9710 return null;
9711 }
9712
9713 if (!r.crashing && !r.notResponding) {
9714 return null;
9715 }
9716
Dan Egnorb7f03672009-12-09 16:22:32 -08009717 ApplicationErrorReport report = new ApplicationErrorReport();
9718 report.packageName = r.info.packageName;
9719 report.installerPackageName = r.errorReportReceiver.getPackageName();
9720 report.processName = r.processName;
9721 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009722 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009723
Dan Egnorb7f03672009-12-09 16:22:32 -08009724 if (r.crashing) {
9725 report.type = ApplicationErrorReport.TYPE_CRASH;
9726 report.crashInfo = crashInfo;
9727 } else if (r.notResponding) {
9728 report.type = ApplicationErrorReport.TYPE_ANR;
9729 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009730
Dan Egnorb7f03672009-12-09 16:22:32 -08009731 report.anrInfo.activity = r.notRespondingReport.tag;
9732 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9733 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009734 }
9735
Dan Egnorb7f03672009-12-09 16:22:32 -08009736 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009737 }
9738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009739 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9740 // assume our apps are happy - lazy create the list
9741 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9742
9743 synchronized (this) {
9744
9745 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009746 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9747 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009748 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9749 // This one's in trouble, so we'll generate a report for it
9750 // crashes are higher priority (in case there's a crash *and* an anr)
9751 ActivityManager.ProcessErrorStateInfo report = null;
9752 if (app.crashing) {
9753 report = app.crashingReport;
9754 } else if (app.notResponding) {
9755 report = app.notRespondingReport;
9756 }
9757
9758 if (report != null) {
9759 if (errList == null) {
9760 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9761 }
9762 errList.add(report);
9763 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009764 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765 " crashing = " + app.crashing +
9766 " notResponding = " + app.notResponding);
9767 }
9768 }
9769 }
9770 }
9771
9772 return errList;
9773 }
9774
9775 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9776 // Lazy instantiation of list
9777 List<ActivityManager.RunningAppProcessInfo> runList = null;
9778 synchronized (this) {
9779 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009780 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9781 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009782 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9783 // Generate process state info for running application
9784 ActivityManager.RunningAppProcessInfo currApp =
9785 new ActivityManager.RunningAppProcessInfo(app.processName,
9786 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009787 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009789 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009790 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9791 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9792 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009793 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9794 } else if (adj >= HOME_APP_ADJ) {
9795 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9796 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009797 } else if (adj >= SECONDARY_SERVER_ADJ) {
9798 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07009799 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
9800 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
9801 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
9802 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009803 } else if (adj >= VISIBLE_APP_ADJ) {
9804 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9805 } else {
9806 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9807 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009808 currApp.importanceReasonCode = app.adjTypeCode;
9809 if (app.adjSource instanceof ProcessRecord) {
9810 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9811 } else if (app.adjSource instanceof HistoryRecord) {
9812 HistoryRecord r = (HistoryRecord)app.adjSource;
9813 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9814 }
9815 if (app.adjTarget instanceof ComponentName) {
9816 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9817 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009818 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009819 // + " lru=" + currApp.lru);
9820 if (runList == null) {
9821 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9822 }
9823 runList.add(currApp);
9824 }
9825 }
9826 }
9827 return runList;
9828 }
9829
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009830 public List<ApplicationInfo> getRunningExternalApplications() {
9831 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9832 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9833 if (runningApps != null && runningApps.size() > 0) {
9834 Set<String> extList = new HashSet<String>();
9835 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9836 if (app.pkgList != null) {
9837 for (String pkg : app.pkgList) {
9838 extList.add(pkg);
9839 }
9840 }
9841 }
9842 IPackageManager pm = ActivityThread.getPackageManager();
9843 for (String pkg : extList) {
9844 try {
9845 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9846 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9847 retList.add(info);
9848 }
9849 } catch (RemoteException e) {
9850 }
9851 }
9852 }
9853 return retList;
9854 }
9855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009856 @Override
9857 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009858 if (checkCallingPermission(android.Manifest.permission.DUMP)
9859 != PackageManager.PERMISSION_GRANTED) {
9860 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9861 + Binder.getCallingPid()
9862 + ", uid=" + Binder.getCallingUid()
9863 + " without permission "
9864 + android.Manifest.permission.DUMP);
9865 return;
9866 }
9867
9868 boolean dumpAll = false;
9869
9870 int opti = 0;
9871 while (opti < args.length) {
9872 String opt = args[opti];
9873 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9874 break;
9875 }
9876 opti++;
9877 if ("-a".equals(opt)) {
9878 dumpAll = true;
9879 } else if ("-h".equals(opt)) {
9880 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009881 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009882 pw.println(" cmd may be one of:");
9883 pw.println(" activities: activity stack state");
9884 pw.println(" broadcasts: broadcast state");
9885 pw.println(" intents: pending intent state");
9886 pw.println(" processes: process state");
9887 pw.println(" providers: content provider state");
9888 pw.println(" services: service state");
9889 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009890 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009891 } else {
9892 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009893 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009894 }
9895
9896 // Is the caller requesting to dump a particular piece of data?
9897 if (opti < args.length) {
9898 String cmd = args[opti];
9899 opti++;
9900 if ("activities".equals(cmd) || "a".equals(cmd)) {
9901 synchronized (this) {
9902 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009903 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009904 return;
9905 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9906 synchronized (this) {
9907 dumpBroadcastsLocked(fd, pw, args, opti, true);
9908 }
9909 return;
9910 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9911 synchronized (this) {
9912 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9913 }
9914 return;
9915 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9916 synchronized (this) {
9917 dumpProcessesLocked(fd, pw, args, opti, true);
9918 }
9919 return;
9920 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9921 synchronized (this) {
9922 dumpProvidersLocked(fd, pw, args, opti, true);
9923 }
9924 return;
9925 } else if ("service".equals(cmd)) {
9926 dumpService(fd, pw, args, opti, true);
9927 return;
9928 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9929 synchronized (this) {
9930 dumpServicesLocked(fd, pw, args, opti, true);
9931 }
9932 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009933 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009934 }
9935
9936 // No piece of data specified, dump everything.
9937 synchronized (this) {
9938 boolean needSep;
9939 if (dumpAll) {
9940 pw.println("Providers in Current Activity Manager State:");
9941 }
9942 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9943 if (needSep) {
9944 pw.println(" ");
9945 }
9946 if (dumpAll) {
9947 pw.println("-------------------------------------------------------------------------------");
9948 pw.println("Broadcasts in Current Activity Manager State:");
9949 }
9950 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9951 if (needSep) {
9952 pw.println(" ");
9953 }
9954 if (dumpAll) {
9955 pw.println("-------------------------------------------------------------------------------");
9956 pw.println("Services in Current Activity Manager State:");
9957 }
9958 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9959 if (needSep) {
9960 pw.println(" ");
9961 }
9962 if (dumpAll) {
9963 pw.println("-------------------------------------------------------------------------------");
9964 pw.println("PendingIntents in Current Activity Manager State:");
9965 }
9966 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9967 if (needSep) {
9968 pw.println(" ");
9969 }
9970 if (dumpAll) {
9971 pw.println("-------------------------------------------------------------------------------");
9972 pw.println("Activities in Current Activity Manager State:");
9973 }
9974 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9975 if (needSep) {
9976 pw.println(" ");
9977 }
9978 if (dumpAll) {
9979 pw.println("-------------------------------------------------------------------------------");
9980 pw.println("Processes in Current Activity Manager State:");
9981 }
9982 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9983 }
9984 }
9985
9986 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9987 int opti, boolean dumpAll, boolean needHeader) {
9988 if (needHeader) {
9989 pw.println(" Activity stack:");
9990 }
9991 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9992 pw.println(" ");
9993 pw.println(" Running activities (most recent first):");
9994 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9995 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009996 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009997 pw.println(" Activities waiting for another to become visible:");
9998 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9999 }
10000 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010002 pw.println(" Activities waiting to stop:");
10003 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
10004 }
10005 if (mFinishingActivities.size() > 0) {
10006 pw.println(" ");
10007 pw.println(" Activities waiting to finish:");
10008 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
10009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010010
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010011 pw.println(" ");
10012 pw.println(" mPausingActivity: " + mPausingActivity);
10013 pw.println(" mResumedActivity: " + mResumedActivity);
10014 pw.println(" mFocusedActivity: " + mFocusedActivity);
10015 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010016
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010017 if (dumpAll && mRecentTasks.size() > 0) {
10018 pw.println(" ");
10019 pw.println("Recent tasks in Current Activity Manager State:");
10020
10021 final int N = mRecentTasks.size();
10022 for (int i=0; i<N; i++) {
10023 TaskRecord tr = mRecentTasks.get(i);
10024 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
10025 pw.println(tr);
10026 mRecentTasks.get(i).dump(pw, " ");
10027 }
10028 }
10029
10030 pw.println(" ");
10031 pw.println(" mCurTask: " + mCurTask);
10032
10033 return true;
10034 }
10035
10036 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10037 int opti, boolean dumpAll) {
10038 boolean needSep = false;
10039 int numPers = 0;
10040
10041 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010042 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
10043 final int NA = procs.size();
10044 for (int ia=0; ia<NA; ia++) {
10045 if (!needSep) {
10046 pw.println(" All known processes:");
10047 needSep = true;
10048 }
10049 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010050 pw.print(r.persistent ? " *PERS*" : " *APP*");
10051 pw.print(" UID "); pw.print(procs.keyAt(ia));
10052 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010053 r.dump(pw, " ");
10054 if (r.persistent) {
10055 numPers++;
10056 }
10057 }
10058 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010059 }
10060
10061 if (mLruProcesses.size() > 0) {
10062 if (needSep) pw.println(" ");
10063 needSep = true;
10064 pw.println(" Running processes (most recent first):");
10065 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010066 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010067 needSep = true;
10068 }
10069
10070 synchronized (mPidsSelfLocked) {
10071 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010072 if (needSep) pw.println(" ");
10073 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010074 pw.println(" PID mappings:");
10075 for (int i=0; i<mPidsSelfLocked.size(); i++) {
10076 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
10077 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010078 }
10079 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010080 }
10081
10082 if (mForegroundProcesses.size() > 0) {
10083 if (needSep) pw.println(" ");
10084 needSep = true;
10085 pw.println(" Foreground Processes:");
10086 for (int i=0; i<mForegroundProcesses.size(); i++) {
10087 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
10088 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010089 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010090 }
10091
10092 if (mPersistentStartingProcesses.size() > 0) {
10093 if (needSep) pw.println(" ");
10094 needSep = true;
10095 pw.println(" Persisent processes that are starting:");
10096 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
10097 "Starting Norm", "Restarting PERS", false);
10098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010099
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010100 if (mStartingProcesses.size() > 0) {
10101 if (needSep) pw.println(" ");
10102 needSep = true;
10103 pw.println(" Processes that are starting:");
10104 dumpProcessList(pw, this, mStartingProcesses, " ",
10105 "Starting Norm", "Starting PERS", false);
10106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010107
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010108 if (mRemovedProcesses.size() > 0) {
10109 if (needSep) pw.println(" ");
10110 needSep = true;
10111 pw.println(" Processes that are being removed:");
10112 dumpProcessList(pw, this, mRemovedProcesses, " ",
10113 "Removed Norm", "Removed PERS", false);
10114 }
10115
10116 if (mProcessesOnHold.size() > 0) {
10117 if (needSep) pw.println(" ");
10118 needSep = true;
10119 pw.println(" Processes that are on old until the system is ready:");
10120 dumpProcessList(pw, this, mProcessesOnHold, " ",
10121 "OnHold Norm", "OnHold PERS", false);
10122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010123
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010124 if (mProcessesToGc.size() > 0) {
10125 if (needSep) pw.println(" ");
10126 needSep = true;
10127 pw.println(" Processes that are waiting to GC:");
10128 long now = SystemClock.uptimeMillis();
10129 for (int i=0; i<mProcessesToGc.size(); i++) {
10130 ProcessRecord proc = mProcessesToGc.get(i);
10131 pw.print(" Process "); pw.println(proc);
10132 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
10133 pw.print(", last gced=");
10134 pw.print(now-proc.lastRequestedGc);
10135 pw.print(" ms ago, last lowMem=");
10136 pw.print(now-proc.lastLowMemory);
10137 pw.println(" ms ago");
10138
10139 }
10140 }
10141
10142 if (mProcessCrashTimes.getMap().size() > 0) {
10143 if (needSep) pw.println(" ");
10144 needSep = true;
10145 pw.println(" Time since processes crashed:");
10146 long now = SystemClock.uptimeMillis();
10147 for (Map.Entry<String, SparseArray<Long>> procs
10148 : mProcessCrashTimes.getMap().entrySet()) {
10149 SparseArray<Long> uids = procs.getValue();
10150 final int N = uids.size();
10151 for (int i=0; i<N; i++) {
10152 pw.print(" Process "); pw.print(procs.getKey());
10153 pw.print(" uid "); pw.print(uids.keyAt(i));
10154 pw.print(": last crashed ");
10155 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010156 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010157 }
10158 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010160
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010161 if (mBadProcesses.getMap().size() > 0) {
10162 if (needSep) pw.println(" ");
10163 needSep = true;
10164 pw.println(" Bad processes:");
10165 for (Map.Entry<String, SparseArray<Long>> procs
10166 : mBadProcesses.getMap().entrySet()) {
10167 SparseArray<Long> uids = procs.getValue();
10168 final int N = uids.size();
10169 for (int i=0; i<N; i++) {
10170 pw.print(" Bad process "); pw.print(procs.getKey());
10171 pw.print(" uid "); pw.print(uids.keyAt(i));
10172 pw.print(": crashed at time ");
10173 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010174 }
10175 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010177
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010178 pw.println(" ");
10179 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010180 if (mHeavyWeightProcess != null) {
10181 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
10182 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010183 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -070010184 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010185 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
10186 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
10187 || mOrigWaitForDebugger) {
10188 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
10189 + " mDebugTransient=" + mDebugTransient
10190 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
10191 }
10192 if (mAlwaysFinishActivities || mController != null) {
10193 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
10194 + " mController=" + mController);
10195 }
10196 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010197 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010198 pw.println(" mStartRunning=" + mStartRunning
10199 + " mSystemReady=" + mSystemReady
10200 + " mBooting=" + mBooting
10201 + " mBooted=" + mBooted
10202 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010203 pw.println(" mGoingToSleep=" + mGoingToSleep);
10204 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -070010205 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010206 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010207
10208 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010209 }
10210
10211 /**
10212 * There are three ways to call this:
10213 * - no service specified: dump all the services
10214 * - a flattened component name that matched an existing service was specified as the
10215 * first arg: dump that one service
10216 * - the first arg isn't the flattened component name of an existing service:
10217 * dump all services whose component contains the first arg as a substring
10218 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010219 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
10220 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010221 String[] newArgs;
10222 String componentNameString;
10223 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -080010224 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010225 componentNameString = null;
10226 newArgs = EMPTY_STRING_ARRAY;
10227 r = null;
10228 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010229 componentNameString = args[opti];
10230 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010231 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
10232 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010233 newArgs = new String[args.length - opti];
10234 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010235 }
10236
10237 if (r != null) {
10238 dumpService(fd, pw, r, newArgs);
10239 } else {
10240 for (ServiceRecord r1 : mServices.values()) {
10241 if (componentNameString == null
10242 || r1.name.flattenToString().contains(componentNameString)) {
10243 dumpService(fd, pw, r1, newArgs);
10244 }
10245 }
10246 }
10247 }
10248
10249 /**
10250 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
10251 * there is a thread associated with the service.
10252 */
10253 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
10254 pw.println(" Service " + r.name.flattenToString());
10255 if (r.app != null && r.app.thread != null) {
10256 try {
10257 // flush anything that is already in the PrintWriter since the thread is going
10258 // to write to the file descriptor directly
10259 pw.flush();
10260 r.app.thread.dumpService(fd, r, args);
10261 pw.print("\n");
10262 } catch (RemoteException e) {
10263 pw.println("got a RemoteException while dumping the service");
10264 }
10265 }
10266 }
10267
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010268 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10269 int opti, boolean dumpAll) {
10270 boolean needSep = false;
10271
10272 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010273 if (mRegisteredReceivers.size() > 0) {
10274 pw.println(" ");
10275 pw.println(" Registered Receivers:");
10276 Iterator it = mRegisteredReceivers.values().iterator();
10277 while (it.hasNext()) {
10278 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010279 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010280 r.dump(pw, " ");
10281 }
10282 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 pw.println(" ");
10285 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010286 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010287 needSep = true;
10288 }
10289
10290 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
10291 || mPendingBroadcast != null) {
10292 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010293 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010294 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010295 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010296 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10297 pw.println(" Broadcast #" + i + ":");
10298 mParallelBroadcasts.get(i).dump(pw, " ");
10299 }
10300 if (mOrderedBroadcasts.size() > 0) {
10301 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010302 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010303 }
10304 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10305 pw.println(" Serialized Broadcast #" + i + ":");
10306 mOrderedBroadcasts.get(i).dump(pw, " ");
10307 }
10308 pw.println(" ");
10309 pw.println(" Pending broadcast:");
10310 if (mPendingBroadcast != null) {
10311 mPendingBroadcast.dump(pw, " ");
10312 } else {
10313 pw.println(" (null)");
10314 }
10315 needSep = true;
10316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010317
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010318 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010319 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -080010320 pw.println(" Historical broadcasts:");
10321 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
10322 BroadcastRecord r = mBroadcastHistory[i];
10323 if (r == null) {
10324 break;
10325 }
10326 pw.println(" Historical Broadcast #" + i + ":");
10327 r.dump(pw, " ");
10328 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010329 needSep = true;
10330 }
10331
10332 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010333 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010334 pw.println(" Sticky broadcasts:");
10335 StringBuilder sb = new StringBuilder(128);
10336 for (Map.Entry<String, ArrayList<Intent>> ent
10337 : mStickyBroadcasts.entrySet()) {
10338 pw.print(" * Sticky action "); pw.print(ent.getKey());
10339 pw.println(":");
10340 ArrayList<Intent> intents = ent.getValue();
10341 final int N = intents.size();
10342 for (int i=0; i<N; i++) {
10343 sb.setLength(0);
10344 sb.append(" Intent: ");
10345 intents.get(i).toShortString(sb, true, false);
10346 pw.println(sb.toString());
10347 Bundle bundle = intents.get(i).getExtras();
10348 if (bundle != null) {
10349 pw.print(" ");
10350 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010351 }
10352 }
10353 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010354 needSep = true;
10355 }
10356
10357 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010358 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010359 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010360 pw.println(" mHandler:");
10361 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010362 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010363 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010364
10365 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010366 }
10367
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010368 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10369 int opti, boolean dumpAll) {
10370 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010372 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 if (mServices.size() > 0) {
10374 pw.println(" Active services:");
10375 Iterator<ServiceRecord> it = mServices.values().iterator();
10376 while (it.hasNext()) {
10377 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010378 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010379 r.dump(pw, " ");
10380 }
10381 needSep = true;
10382 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010384
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010385 if (mPendingServices.size() > 0) {
10386 if (needSep) pw.println(" ");
10387 pw.println(" Pending services:");
10388 for (int i=0; i<mPendingServices.size(); i++) {
10389 ServiceRecord r = mPendingServices.get(i);
10390 pw.print(" * Pending "); pw.println(r);
10391 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010392 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010393 needSep = true;
10394 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010395
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010396 if (mRestartingServices.size() > 0) {
10397 if (needSep) pw.println(" ");
10398 pw.println(" Restarting services:");
10399 for (int i=0; i<mRestartingServices.size(); i++) {
10400 ServiceRecord r = mRestartingServices.get(i);
10401 pw.print(" * Restarting "); pw.println(r);
10402 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010403 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010404 needSep = true;
10405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010406
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010407 if (mStoppingServices.size() > 0) {
10408 if (needSep) pw.println(" ");
10409 pw.println(" Stopping services:");
10410 for (int i=0; i<mStoppingServices.size(); i++) {
10411 ServiceRecord r = mStoppingServices.get(i);
10412 pw.print(" * Stopping "); pw.println(r);
10413 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010414 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010415 needSep = true;
10416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010417
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010418 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010419 if (mServiceConnections.size() > 0) {
10420 if (needSep) pw.println(" ");
10421 pw.println(" Connection bindings to services:");
10422 Iterator<ConnectionRecord> it
10423 = mServiceConnections.values().iterator();
10424 while (it.hasNext()) {
10425 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010426 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 r.dump(pw, " ");
10428 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010429 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430 }
10431 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010432
10433 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010434 }
10435
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010436 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10437 int opti, boolean dumpAll) {
10438 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010439
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010440 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010441 if (mProvidersByClass.size() > 0) {
10442 if (needSep) pw.println(" ");
10443 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010444 Iterator<Map.Entry<String, ContentProviderRecord>> it
10445 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010447 Map.Entry<String, ContentProviderRecord> e = it.next();
10448 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010449 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010450 r.dump(pw, " ");
10451 }
10452 needSep = true;
10453 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010454
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010455 if (mProvidersByName.size() > 0) {
10456 pw.println(" ");
10457 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010458 Iterator<Map.Entry<String, ContentProviderRecord>> it
10459 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010460 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010461 Map.Entry<String, ContentProviderRecord> e = it.next();
10462 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010463 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10464 pw.println(r);
10465 }
10466 needSep = true;
10467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010468 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010469
10470 if (mLaunchingProviders.size() > 0) {
10471 if (needSep) pw.println(" ");
10472 pw.println(" Launching content providers:");
10473 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10474 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10475 pw.println(mLaunchingProviders.get(i));
10476 }
10477 needSep = true;
10478 }
10479
10480 if (mGrantedUriPermissions.size() > 0) {
10481 pw.println();
10482 pw.println("Granted Uri Permissions:");
10483 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10484 int uid = mGrantedUriPermissions.keyAt(i);
10485 HashMap<Uri, UriPermission> perms
10486 = mGrantedUriPermissions.valueAt(i);
10487 pw.print(" * UID "); pw.print(uid);
10488 pw.println(" holds:");
10489 for (UriPermission perm : perms.values()) {
10490 pw.print(" "); pw.println(perm);
10491 perm.dump(pw, " ");
10492 }
10493 }
10494 needSep = true;
10495 }
10496
10497 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010498 }
10499
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010500 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10501 int opti, boolean dumpAll) {
10502 boolean needSep = false;
10503
10504 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010505 if (this.mIntentSenderRecords.size() > 0) {
10506 Iterator<WeakReference<PendingIntentRecord>> it
10507 = mIntentSenderRecords.values().iterator();
10508 while (it.hasNext()) {
10509 WeakReference<PendingIntentRecord> ref = it.next();
10510 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010511 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010512 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010513 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010514 rec.dump(pw, " ");
10515 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010516 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010517 }
10518 }
10519 }
10520 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010521
10522 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010523 }
10524
10525 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010526 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010527 TaskRecord lastTask = null;
10528 for (int i=list.size()-1; i>=0; i--) {
10529 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010530 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010531 if (lastTask != r.task) {
10532 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010533 pw.print(prefix);
10534 pw.print(full ? "* " : " ");
10535 pw.println(lastTask);
10536 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010537 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010540 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10541 pw.print(" #"); pw.print(i); pw.print(": ");
10542 pw.println(r);
10543 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010544 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 }
10547 }
10548
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010549 private static String buildOomTag(String prefix, String space, int val, int base) {
10550 if (val == base) {
10551 if (space == null) return prefix;
10552 return prefix + " ";
10553 }
10554 return prefix + "+" + Integer.toString(val-base);
10555 }
10556
10557 private static final int dumpProcessList(PrintWriter pw,
10558 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010559 String prefix, String normalLabel, String persistentLabel,
10560 boolean inclOomAdj) {
10561 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010562 final int N = list.size()-1;
10563 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010564 ProcessRecord r = (ProcessRecord)list.get(i);
10565 if (false) {
10566 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10567 + " #" + i + ":");
10568 r.dump(pw, prefix + " ");
10569 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010570 String oomAdj;
10571 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010572 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010573 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010574 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10575 } else if (r.setAdj >= HOME_APP_ADJ) {
10576 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10577 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10578 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10579 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10580 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010581 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
10582 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
10583 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
10584 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010585 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10586 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10587 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10588 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010589 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010590 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010591 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010592 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010593 } else {
10594 oomAdj = Integer.toString(r.setAdj);
10595 }
10596 String schedGroup;
10597 switch (r.setSchedGroup) {
10598 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10599 schedGroup = "B";
10600 break;
10601 case Process.THREAD_GROUP_DEFAULT:
10602 schedGroup = "F";
10603 break;
10604 default:
10605 schedGroup = Integer.toString(r.setSchedGroup);
10606 break;
10607 }
10608 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010609 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010610 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010611 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010612 pw.print(prefix);
10613 pw.print(" ");
10614 if (r.adjTarget instanceof ComponentName) {
10615 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
10616 } else if (r.adjTarget != null) {
10617 pw.print(r.adjTarget.toString());
10618 } else {
10619 pw.print("{null}");
10620 }
10621 pw.print("<=");
10622 if (r.adjSource instanceof ProcessRecord) {
10623 pw.print("Proc{");
10624 pw.print(((ProcessRecord)r.adjSource).toShortString());
10625 pw.println("}");
10626 } else if (r.adjSource != null) {
10627 pw.println(r.adjSource.toString());
10628 } else {
10629 pw.println("{null}");
10630 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010632 } else {
10633 pw.println(String.format("%s%s #%2d: %s",
10634 prefix, (r.persistent ? persistentLabel : normalLabel),
10635 i, r.toString()));
10636 }
10637 if (r.persistent) {
10638 numPers++;
10639 }
10640 }
10641 return numPers;
10642 }
10643
Dianne Hackborn472ad872010-04-07 17:31:48 -070010644 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010645 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010646 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010647 long uptime = SystemClock.uptimeMillis();
10648 long realtime = SystemClock.elapsedRealtime();
10649
10650 if (isCheckinRequest) {
10651 // short checkin version
10652 pw.println(uptime + "," + realtime);
10653 pw.flush();
10654 } else {
10655 pw.println("Applications Memory Usage (kB):");
10656 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10657 }
10658 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10659 ProcessRecord r = (ProcessRecord)list.get(i);
10660 if (r.thread != null) {
10661 if (!isCheckinRequest) {
10662 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10663 pw.flush();
10664 }
10665 try {
10666 r.thread.asBinder().dump(fd, args);
10667 } catch (RemoteException e) {
10668 if (!isCheckinRequest) {
10669 pw.println("Got RemoteException!");
10670 pw.flush();
10671 }
10672 }
10673 }
10674 }
10675 }
10676
10677 /**
10678 * Searches array of arguments for the specified string
10679 * @param args array of argument strings
10680 * @param value value to search for
10681 * @return true if the value is contained in the array
10682 */
10683 private static boolean scanArgs(String[] args, String value) {
10684 if (args != null) {
10685 for (String arg : args) {
10686 if (value.equals(arg)) {
10687 return true;
10688 }
10689 }
10690 }
10691 return false;
10692 }
10693
Dianne Hackborn75b03852009-06-12 15:43:26 -070010694 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010695 int count = mHistory.size();
10696
10697 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010698 int index = -1;
10699 for (int i=count-1; i>=0; i--) {
10700 Object o = mHistory.get(i);
10701 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010702 index = i;
10703 break;
10704 }
10705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010706
10707 return index;
10708 }
10709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010710 private final void killServicesLocked(ProcessRecord app,
10711 boolean allowRestart) {
10712 // Report disconnected services.
10713 if (false) {
10714 // XXX we are letting the client link to the service for
10715 // death notifications.
10716 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010717 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010718 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010719 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010720 if (r.connections.size() > 0) {
10721 Iterator<ConnectionRecord> jt
10722 = r.connections.values().iterator();
10723 while (jt.hasNext()) {
10724 ConnectionRecord c = jt.next();
10725 if (c.binding.client != app) {
10726 try {
10727 //c.conn.connected(r.className, null);
10728 } catch (Exception e) {
10729 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010730 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010731 + r.shortName
10732 + " from app " + app.processName, e);
10733 }
10734 }
10735 }
10736 }
10737 }
10738 }
10739 }
10740
10741 // Clean up any connections this application has to other services.
10742 if (app.connections.size() > 0) {
10743 Iterator<ConnectionRecord> it = app.connections.iterator();
10744 while (it.hasNext()) {
10745 ConnectionRecord r = it.next();
10746 removeConnectionLocked(r, app, null);
10747 }
10748 }
10749 app.connections.clear();
10750
10751 if (app.services.size() != 0) {
10752 // Any services running in the application need to be placed
10753 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010754 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010755 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010756 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010757 synchronized (sr.stats.getBatteryStats()) {
10758 sr.stats.stopLaunchedLocked();
10759 }
10760 sr.app = null;
10761 sr.executeNesting = 0;
10762 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010763
10764 boolean hasClients = sr.bindings.size() > 0;
10765 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010766 Iterator<IntentBindRecord> bindings
10767 = sr.bindings.values().iterator();
10768 while (bindings.hasNext()) {
10769 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010770 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010771 + ": shouldUnbind=" + b.hasBound);
10772 b.binder = null;
10773 b.requested = b.received = b.hasBound = false;
10774 }
10775 }
10776
10777 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010778 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010779 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010780 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010781 sr.crashCount, sr.shortName, app.pid);
10782 bringDownServiceLocked(sr, true);
10783 } else if (!allowRestart) {
10784 bringDownServiceLocked(sr, true);
10785 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010786 boolean canceled = scheduleServiceRestartLocked(sr, true);
10787
10788 // Should the service remain running? Note that in the
10789 // extreme case of so many attempts to deliver a command
10790 // that it failed, that we also will stop it here.
10791 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10792 if (sr.pendingStarts.size() == 0) {
10793 sr.startRequested = false;
10794 if (!hasClients) {
10795 // Whoops, no reason to restart!
10796 bringDownServiceLocked(sr, true);
10797 }
10798 }
10799 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010800 }
10801 }
10802
10803 if (!allowRestart) {
10804 app.services.clear();
10805 }
10806 }
10807
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010808 // Make sure we have no more records on the stopping list.
10809 int i = mStoppingServices.size();
10810 while (i > 0) {
10811 i--;
10812 ServiceRecord sr = mStoppingServices.get(i);
10813 if (sr.app == app) {
10814 mStoppingServices.remove(i);
10815 }
10816 }
10817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010818 app.executingServices.clear();
10819 }
10820
10821 private final void removeDyingProviderLocked(ProcessRecord proc,
10822 ContentProviderRecord cpr) {
10823 synchronized (cpr) {
10824 cpr.launchingApp = null;
10825 cpr.notifyAll();
10826 }
10827
10828 mProvidersByClass.remove(cpr.info.name);
10829 String names[] = cpr.info.authority.split(";");
10830 for (int j = 0; j < names.length; j++) {
10831 mProvidersByName.remove(names[j]);
10832 }
10833
10834 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10835 while (cit.hasNext()) {
10836 ProcessRecord capp = cit.next();
10837 if (!capp.persistent && capp.thread != null
10838 && capp.pid != 0
10839 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010840 Slog.i(TAG, "Kill " + capp.processName
10841 + " (pid " + capp.pid + "): provider " + cpr.info.name
10842 + " in dying process " + proc.processName);
10843 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10844 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010845 Process.killProcess(capp.pid);
10846 }
10847 }
10848
10849 mLaunchingProviders.remove(cpr);
10850 }
10851
10852 /**
10853 * Main code for cleaning up a process when it has gone away. This is
10854 * called both as a result of the process dying, or directly when stopping
10855 * a process when running in single process mode.
10856 */
10857 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10858 boolean restarting, int index) {
10859 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010860 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010861 }
10862
Dianne Hackborn36124872009-10-08 16:22:03 -070010863 mProcessesToGc.remove(app);
10864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010865 // Dismiss any open dialogs.
10866 if (app.crashDialog != null) {
10867 app.crashDialog.dismiss();
10868 app.crashDialog = null;
10869 }
10870 if (app.anrDialog != null) {
10871 app.anrDialog.dismiss();
10872 app.anrDialog = null;
10873 }
10874 if (app.waitDialog != null) {
10875 app.waitDialog.dismiss();
10876 app.waitDialog = null;
10877 }
10878
10879 app.crashing = false;
10880 app.notResponding = false;
10881
10882 app.resetPackageList();
10883 app.thread = null;
10884 app.forcingToForeground = null;
10885 app.foregroundServices = false;
10886
10887 killServicesLocked(app, true);
10888
10889 boolean restart = false;
10890
10891 int NL = mLaunchingProviders.size();
10892
10893 // Remove published content providers.
10894 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010895 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010896 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010897 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 cpr.provider = null;
10899 cpr.app = null;
10900
10901 // See if someone is waiting for this provider... in which
10902 // case we don't remove it, but just let it restart.
10903 int i = 0;
10904 if (!app.bad) {
10905 for (; i<NL; i++) {
10906 if (mLaunchingProviders.get(i) == cpr) {
10907 restart = true;
10908 break;
10909 }
10910 }
10911 } else {
10912 i = NL;
10913 }
10914
10915 if (i >= NL) {
10916 removeDyingProviderLocked(app, cpr);
10917 NL = mLaunchingProviders.size();
10918 }
10919 }
10920 app.pubProviders.clear();
10921 }
10922
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010923 // Take care of any launching providers waiting for this process.
10924 if (checkAppInLaunchingProvidersLocked(app, false)) {
10925 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010926 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010928 // Unregister from connected content providers.
10929 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010930 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010931 while (it.hasNext()) {
10932 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10933 cpr.clients.remove(app);
10934 }
10935 app.conProviders.clear();
10936 }
10937
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010938 // At this point there may be remaining entries in mLaunchingProviders
10939 // where we were the only one waiting, so they are no longer of use.
10940 // Look for these and clean up if found.
10941 // XXX Commented out for now. Trying to figure out a way to reproduce
10942 // the actual situation to identify what is actually going on.
10943 if (false) {
10944 for (int i=0; i<NL; i++) {
10945 ContentProviderRecord cpr = (ContentProviderRecord)
10946 mLaunchingProviders.get(i);
10947 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10948 synchronized (cpr) {
10949 cpr.launchingApp = null;
10950 cpr.notifyAll();
10951 }
10952 }
10953 }
10954 }
10955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010956 skipCurrentReceiverLocked(app);
10957
10958 // Unregister any receivers.
10959 if (app.receivers.size() > 0) {
10960 Iterator<ReceiverList> it = app.receivers.iterator();
10961 while (it.hasNext()) {
10962 removeReceiverLocked(it.next());
10963 }
10964 app.receivers.clear();
10965 }
10966
Christopher Tate181fafa2009-05-14 11:12:14 -070010967 // If the app is undergoing backup, tell the backup manager about it
10968 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010969 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010970 try {
10971 IBackupManager bm = IBackupManager.Stub.asInterface(
10972 ServiceManager.getService(Context.BACKUP_SERVICE));
10973 bm.agentDisconnected(app.info.packageName);
10974 } catch (RemoteException e) {
10975 // can't happen; backup manager is local
10976 }
10977 }
10978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979 // If the caller is restarting this app, then leave it in its
10980 // current lists and let the caller take care of it.
10981 if (restarting) {
10982 return;
10983 }
10984
10985 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010986 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010987 "Removing non-persistent process during cleanup: " + app);
10988 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010989 if (mHeavyWeightProcess == app) {
10990 mHeavyWeightProcess = null;
10991 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
10992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010993 } else if (!app.removed) {
10994 // This app is persistent, so we need to keep its record around.
10995 // If it is not already on the pending app list, add it there
10996 // and start a new process for it.
10997 app.thread = null;
10998 app.forcingToForeground = null;
10999 app.foregroundServices = false;
11000 if (mPersistentStartingProcesses.indexOf(app) < 0) {
11001 mPersistentStartingProcesses.add(app);
11002 restart = true;
11003 }
11004 }
11005 mProcessesOnHold.remove(app);
11006
The Android Open Source Project4df24232009-03-05 14:34:35 -080011007 if (app == mHomeProcess) {
11008 mHomeProcess = null;
11009 }
11010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 if (restart) {
11012 // We have components that still need to be running in the
11013 // process, so re-launch it.
11014 mProcessNames.put(app.processName, app.info.uid, app);
11015 startProcessLocked(app, "restart", app.processName);
11016 } else if (app.pid > 0 && app.pid != MY_PID) {
11017 // Goodbye!
11018 synchronized (mPidsSelfLocked) {
11019 mPidsSelfLocked.remove(app.pid);
11020 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
11021 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070011022 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 }
11024 }
11025
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011026 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
11027 // Look through the content providers we are waiting to have launched,
11028 // and if any run in this process then either schedule a restart of
11029 // the process or kill the client waiting for it if this process has
11030 // gone bad.
11031 int NL = mLaunchingProviders.size();
11032 boolean restart = false;
11033 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011034 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011035 if (cpr.launchingApp == app) {
11036 if (!alwaysBad && !app.bad) {
11037 restart = true;
11038 } else {
11039 removeDyingProviderLocked(app, cpr);
11040 NL = mLaunchingProviders.size();
11041 }
11042 }
11043 }
11044 return restart;
11045 }
11046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011047 // =========================================================
11048 // SERVICES
11049 // =========================================================
11050
11051 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
11052 ActivityManager.RunningServiceInfo info =
11053 new ActivityManager.RunningServiceInfo();
11054 info.service = r.name;
11055 if (r.app != null) {
11056 info.pid = r.app.pid;
11057 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011058 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011059 info.process = r.processName;
11060 info.foreground = r.isForeground;
11061 info.activeSince = r.createTime;
11062 info.started = r.startRequested;
11063 info.clientCount = r.connections.size();
11064 info.crashCount = r.crashCount;
11065 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011066 if (r.isForeground) {
11067 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
11068 }
11069 if (r.startRequested) {
11070 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
11071 }
Dan Egnor42471dd2010-01-07 17:25:22 -080011072 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011073 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
11074 }
11075 if (r.app != null && r.app.persistent) {
11076 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
11077 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011078 for (ConnectionRecord conn : r.connections.values()) {
11079 if (conn.clientLabel != 0) {
11080 info.clientPackage = conn.binding.client.info.packageName;
11081 info.clientLabel = conn.clientLabel;
11082 break;
11083 }
11084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011085 return info;
11086 }
11087
11088 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
11089 int flags) {
11090 synchronized (this) {
11091 ArrayList<ActivityManager.RunningServiceInfo> res
11092 = new ArrayList<ActivityManager.RunningServiceInfo>();
11093
11094 if (mServices.size() > 0) {
11095 Iterator<ServiceRecord> it = mServices.values().iterator();
11096 while (it.hasNext() && res.size() < maxNum) {
11097 res.add(makeRunningServiceInfoLocked(it.next()));
11098 }
11099 }
11100
11101 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
11102 ServiceRecord r = mRestartingServices.get(i);
11103 ActivityManager.RunningServiceInfo info =
11104 makeRunningServiceInfoLocked(r);
11105 info.restarting = r.nextRestartTime;
11106 res.add(info);
11107 }
11108
11109 return res;
11110 }
11111 }
11112
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011113 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
11114 synchronized (this) {
11115 ServiceRecord r = mServices.get(name);
11116 if (r != null) {
11117 for (ConnectionRecord conn : r.connections.values()) {
11118 if (conn.clientIntent != null) {
11119 return conn.clientIntent;
11120 }
11121 }
11122 }
11123 }
11124 return null;
11125 }
11126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011127 private final ServiceRecord findServiceLocked(ComponentName name,
11128 IBinder token) {
11129 ServiceRecord r = mServices.get(name);
11130 return r == token ? r : null;
11131 }
11132
11133 private final class ServiceLookupResult {
11134 final ServiceRecord record;
11135 final String permission;
11136
11137 ServiceLookupResult(ServiceRecord _record, String _permission) {
11138 record = _record;
11139 permission = _permission;
11140 }
11141 };
11142
11143 private ServiceLookupResult findServiceLocked(Intent service,
11144 String resolvedType) {
11145 ServiceRecord r = null;
11146 if (service.getComponent() != null) {
11147 r = mServices.get(service.getComponent());
11148 }
11149 if (r == null) {
11150 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11151 r = mServicesByIntent.get(filter);
11152 }
11153
11154 if (r == null) {
11155 try {
11156 ResolveInfo rInfo =
11157 ActivityThread.getPackageManager().resolveService(
11158 service, resolvedType, 0);
11159 ServiceInfo sInfo =
11160 rInfo != null ? rInfo.serviceInfo : null;
11161 if (sInfo == null) {
11162 return null;
11163 }
11164
11165 ComponentName name = new ComponentName(
11166 sInfo.applicationInfo.packageName, sInfo.name);
11167 r = mServices.get(name);
11168 } catch (RemoteException ex) {
11169 // pm is in same process, this will never happen.
11170 }
11171 }
11172 if (r != null) {
11173 int callingPid = Binder.getCallingPid();
11174 int callingUid = Binder.getCallingUid();
11175 if (checkComponentPermission(r.permission,
11176 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11177 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011178 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011179 + " from pid=" + callingPid
11180 + ", uid=" + callingUid
11181 + " requires " + r.permission);
11182 return new ServiceLookupResult(null, r.permission);
11183 }
11184 return new ServiceLookupResult(r, null);
11185 }
11186 return null;
11187 }
11188
11189 private class ServiceRestarter implements Runnable {
11190 private ServiceRecord mService;
11191
11192 void setService(ServiceRecord service) {
11193 mService = service;
11194 }
11195
11196 public void run() {
11197 synchronized(ActivityManagerService.this) {
11198 performServiceRestartLocked(mService);
11199 }
11200 }
11201 }
11202
11203 private ServiceLookupResult retrieveServiceLocked(Intent service,
11204 String resolvedType, int callingPid, int callingUid) {
11205 ServiceRecord r = null;
11206 if (service.getComponent() != null) {
11207 r = mServices.get(service.getComponent());
11208 }
11209 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11210 r = mServicesByIntent.get(filter);
11211 if (r == null) {
11212 try {
11213 ResolveInfo rInfo =
11214 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011215 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011216 ServiceInfo sInfo =
11217 rInfo != null ? rInfo.serviceInfo : null;
11218 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011219 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 ": not found");
11221 return null;
11222 }
11223
11224 ComponentName name = new ComponentName(
11225 sInfo.applicationInfo.packageName, sInfo.name);
11226 r = mServices.get(name);
11227 if (r == null) {
11228 filter = new Intent.FilterComparison(service.cloneFilter());
11229 ServiceRestarter res = new ServiceRestarter();
11230 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11231 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11232 synchronized (stats) {
11233 ss = stats.getServiceStatsLocked(
11234 sInfo.applicationInfo.uid, sInfo.packageName,
11235 sInfo.name);
11236 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080011237 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011238 res.setService(r);
11239 mServices.put(name, r);
11240 mServicesByIntent.put(filter, r);
11241
11242 // Make sure this component isn't in the pending list.
11243 int N = mPendingServices.size();
11244 for (int i=0; i<N; i++) {
11245 ServiceRecord pr = mPendingServices.get(i);
11246 if (pr.name.equals(name)) {
11247 mPendingServices.remove(i);
11248 i--;
11249 N--;
11250 }
11251 }
11252 }
11253 } catch (RemoteException ex) {
11254 // pm is in same process, this will never happen.
11255 }
11256 }
11257 if (r != null) {
11258 if (checkComponentPermission(r.permission,
11259 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11260 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011261 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011262 + " from pid=" + Binder.getCallingPid()
11263 + ", uid=" + Binder.getCallingUid()
11264 + " requires " + r.permission);
11265 return new ServiceLookupResult(null, r.permission);
11266 }
11267 return new ServiceLookupResult(r, null);
11268 }
11269 return null;
11270 }
11271
11272 private final void bumpServiceExecutingLocked(ServiceRecord r) {
11273 long now = SystemClock.uptimeMillis();
11274 if (r.executeNesting == 0 && r.app != null) {
11275 if (r.app.executingServices.size() == 0) {
11276 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11277 msg.obj = r.app;
11278 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
11279 }
11280 r.app.executingServices.add(r);
11281 }
11282 r.executeNesting++;
11283 r.executingStart = now;
11284 }
11285
11286 private final void sendServiceArgsLocked(ServiceRecord r,
11287 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011288 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011289 if (N == 0) {
11290 return;
11291 }
11292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011293 int i = 0;
11294 while (i < N) {
11295 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011296 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011297 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011298 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070011299 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011300 // If somehow we got a dummy start at the front, then
11301 // just drop it here.
11302 i++;
11303 continue;
11304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011305 bumpServiceExecutingLocked(r);
11306 if (!oomAdjusted) {
11307 oomAdjusted = true;
11308 updateOomAdjLocked(r.app);
11309 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011310 int flags = 0;
11311 if (si.deliveryCount > 0) {
11312 flags |= Service.START_FLAG_RETRY;
11313 }
11314 if (si.doneExecutingCount > 0) {
11315 flags |= Service.START_FLAG_REDELIVERY;
11316 }
11317 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
11318 si.deliveredTime = SystemClock.uptimeMillis();
11319 r.deliveredStarts.add(si);
11320 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011321 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011322 } catch (RemoteException e) {
11323 // Remote process gone... we'll let the normal cleanup take
11324 // care of this.
11325 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011326 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011327 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011328 break;
11329 }
11330 }
11331 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011332 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011333 } else {
11334 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011335 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011336 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011337 }
11338 }
11339 }
11340
11341 private final boolean requestServiceBindingLocked(ServiceRecord r,
11342 IntentBindRecord i, boolean rebind) {
11343 if (r.app == null || r.app.thread == null) {
11344 // If service is not currently running, can't yet bind.
11345 return false;
11346 }
11347 if ((!i.requested || rebind) && i.apps.size() > 0) {
11348 try {
11349 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011350 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011351 + ": shouldUnbind=" + i.hasBound);
11352 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11353 if (!rebind) {
11354 i.requested = true;
11355 }
11356 i.hasBound = true;
11357 i.doRebind = false;
11358 } catch (RemoteException e) {
11359 return false;
11360 }
11361 }
11362 return true;
11363 }
11364
11365 private final void requestServiceBindingsLocked(ServiceRecord r) {
11366 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11367 while (bindings.hasNext()) {
11368 IntentBindRecord i = bindings.next();
11369 if (!requestServiceBindingLocked(r, i, false)) {
11370 break;
11371 }
11372 }
11373 }
11374
11375 private final void realStartServiceLocked(ServiceRecord r,
11376 ProcessRecord app) throws RemoteException {
11377 if (app.thread == null) {
11378 throw new RemoteException();
11379 }
11380
11381 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011382 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011383
11384 app.services.add(r);
11385 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011386 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387
11388 boolean created = false;
11389 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011390 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011391 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011392 mStringBuilder.setLength(0);
11393 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011394 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011395 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011396 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011397 synchronized (r.stats.getBatteryStats()) {
11398 r.stats.startLaunchedLocked();
11399 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011400 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011401 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011402 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011403 created = true;
11404 } finally {
11405 if (!created) {
11406 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011407 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408 }
11409 }
11410
11411 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011412
11413 // If the service is in the started state, and there are no
11414 // pending arguments, then fake up one so its onStartCommand() will
11415 // be called.
11416 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11417 r.lastStartId++;
11418 if (r.lastStartId < 1) {
11419 r.lastStartId = 1;
11420 }
11421 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11422 }
11423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011424 sendServiceArgsLocked(r, true);
11425 }
11426
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011427 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11428 boolean allowCancel) {
11429 boolean canceled = false;
11430
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011431 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011432 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011433 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011434
11435 // Any delivered but not yet finished starts should be put back
11436 // on the pending list.
11437 final int N = r.deliveredStarts.size();
11438 if (N > 0) {
11439 for (int i=N-1; i>=0; i--) {
11440 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11441 if (si.intent == null) {
11442 // We'll generate this again if needed.
11443 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11444 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11445 r.pendingStarts.add(0, si);
11446 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11447 dur *= 2;
11448 if (minDuration < dur) minDuration = dur;
11449 if (resetTime < dur) resetTime = dur;
11450 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011451 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011452 + r.name);
11453 canceled = true;
11454 }
11455 }
11456 r.deliveredStarts.clear();
11457 }
11458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011459 r.totalRestartCount++;
11460 if (r.restartDelay == 0) {
11461 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011462 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011463 } else {
11464 // If it has been a "reasonably long time" since the service
11465 // was started, then reset our restart duration back to
11466 // the beginning, so we don't infinitely increase the duration
11467 // on a service that just occasionally gets killed (which is
11468 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011469 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011471 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011472 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011473 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011474 if (r.restartDelay < minDuration) {
11475 r.restartDelay = minDuration;
11476 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011477 }
11478 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011479
11480 r.nextRestartTime = now + r.restartDelay;
11481
11482 // Make sure that we don't end up restarting a bunch of services
11483 // all at the same time.
11484 boolean repeat;
11485 do {
11486 repeat = false;
11487 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11488 ServiceRecord r2 = mRestartingServices.get(i);
11489 if (r2 != r && r.nextRestartTime
11490 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11491 && r.nextRestartTime
11492 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11493 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11494 r.restartDelay = r.nextRestartTime - now;
11495 repeat = true;
11496 break;
11497 }
11498 }
11499 } while (repeat);
11500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011501 if (!mRestartingServices.contains(r)) {
11502 mRestartingServices.add(r);
11503 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011504
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011505 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011507 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011508 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011509 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011510 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011512 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 r.shortName, r.restartDelay);
11514
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011515 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011516 }
11517
11518 final void performServiceRestartLocked(ServiceRecord r) {
11519 if (!mRestartingServices.contains(r)) {
11520 return;
11521 }
11522 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11523 }
11524
11525 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11526 if (r.restartDelay == 0) {
11527 return false;
11528 }
11529 r.resetRestartCounter();
11530 mRestartingServices.remove(r);
11531 mHandler.removeCallbacks(r.restarter);
11532 return true;
11533 }
11534
11535 private final boolean bringUpServiceLocked(ServiceRecord r,
11536 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011537 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011538 //r.dump(" ");
11539
Dianne Hackborn36124872009-10-08 16:22:03 -070011540 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541 sendServiceArgsLocked(r, false);
11542 return true;
11543 }
11544
11545 if (!whileRestarting && r.restartDelay > 0) {
11546 // If waiting for a restart, then do nothing.
11547 return true;
11548 }
11549
Joe Onorato8a9b2202010-02-26 18:56:32 -080011550 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011551 + " " + r.intent);
11552
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011553 // We are now bringing the service up, so no longer in the
11554 // restarting state.
11555 mRestartingServices.remove(r);
11556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011557 final String appName = r.processName;
11558 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11559 if (app != null && app.thread != null) {
11560 try {
11561 realStartServiceLocked(r, app);
11562 return true;
11563 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011564 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011565 }
11566
11567 // If a dead object exception was thrown -- fall through to
11568 // restart the application.
11569 }
11570
Dianne Hackborn36124872009-10-08 16:22:03 -070011571 // Not running -- get it started, and enqueue this service record
11572 // to be executed when the app comes up.
11573 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11574 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011575 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011576 + r.appInfo.packageName + "/"
11577 + r.appInfo.uid + " for service "
11578 + r.intent.getIntent() + ": process is bad");
11579 bringDownServiceLocked(r, true);
11580 return false;
11581 }
11582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011583 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011584 mPendingServices.add(r);
11585 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011587 return true;
11588 }
11589
11590 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011591 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011592 //r.dump(" ");
11593
11594 // Does it still need to run?
11595 if (!force && r.startRequested) {
11596 return;
11597 }
11598 if (r.connections.size() > 0) {
11599 if (!force) {
11600 // XXX should probably keep a count of the number of auto-create
11601 // connections directly in the service.
11602 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11603 while (it.hasNext()) {
11604 ConnectionRecord cr = it.next();
11605 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11606 return;
11607 }
11608 }
11609 }
11610
11611 // Report to all of the connections that the service is no longer
11612 // available.
11613 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11614 while (it.hasNext()) {
11615 ConnectionRecord c = it.next();
11616 try {
11617 // todo: shouldn't be a synchronous call!
11618 c.conn.connected(r.name, null);
11619 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011620 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 " to connection " + c.conn.asBinder() +
11622 " (in " + c.binding.client.processName + ")", e);
11623 }
11624 }
11625 }
11626
11627 // Tell the service that it has been unbound.
11628 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11629 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11630 while (it.hasNext()) {
11631 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011632 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633 + ": hasBound=" + ibr.hasBound);
11634 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11635 try {
11636 bumpServiceExecutingLocked(r);
11637 updateOomAdjLocked(r.app);
11638 ibr.hasBound = false;
11639 r.app.thread.scheduleUnbindService(r,
11640 ibr.intent.getIntent());
11641 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011642 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 + r.shortName, e);
11644 serviceDoneExecutingLocked(r, true);
11645 }
11646 }
11647 }
11648 }
11649
Joe Onorato8a9b2202010-02-26 18:56:32 -080011650 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011651 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011652 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011653 System.identityHashCode(r), r.shortName,
11654 (r.app != null) ? r.app.pid : -1);
11655
11656 mServices.remove(r.name);
11657 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011658 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011659 r.totalRestartCount = 0;
11660 unscheduleServiceRestartLocked(r);
11661
11662 // Also make sure it is not on the pending list.
11663 int N = mPendingServices.size();
11664 for (int i=0; i<N; i++) {
11665 if (mPendingServices.get(i) == r) {
11666 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011667 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011668 TAG, "Removed pending service: " + r.shortName);
11669 i--;
11670 N--;
11671 }
11672 }
11673
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011674 r.cancelNotification();
11675 r.isForeground = false;
11676 r.foregroundId = 0;
11677 r.foregroundNoti = null;
11678
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011679 // Clear start entries.
11680 r.deliveredStarts.clear();
11681 r.pendingStarts.clear();
11682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011683 if (r.app != null) {
11684 synchronized (r.stats.getBatteryStats()) {
11685 r.stats.stopLaunchedLocked();
11686 }
11687 r.app.services.remove(r);
11688 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011689 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011690 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011691 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011692 bumpServiceExecutingLocked(r);
11693 mStoppingServices.add(r);
11694 updateOomAdjLocked(r.app);
11695 r.app.thread.scheduleStopService(r);
11696 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011697 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011698 + r.shortName, e);
11699 serviceDoneExecutingLocked(r, true);
11700 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011701 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011702 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011703 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011704 TAG, "Removed service that has no process: " + r.shortName);
11705 }
11706 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011707 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011708 TAG, "Removed service that is not running: " + r.shortName);
11709 }
11710 }
11711
11712 ComponentName startServiceLocked(IApplicationThread caller,
11713 Intent service, String resolvedType,
11714 int callingPid, int callingUid) {
11715 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011716 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011717 + " type=" + resolvedType + " args=" + service.getExtras());
11718
11719 if (caller != null) {
11720 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11721 if (callerApp == null) {
11722 throw new SecurityException(
11723 "Unable to find app for caller " + caller
11724 + " (pid=" + Binder.getCallingPid()
11725 + ") when starting service " + service);
11726 }
11727 }
11728
11729 ServiceLookupResult res =
11730 retrieveServiceLocked(service, resolvedType,
11731 callingPid, callingUid);
11732 if (res == null) {
11733 return null;
11734 }
11735 if (res.record == null) {
11736 return new ComponentName("!", res.permission != null
11737 ? res.permission : "private to package");
11738 }
11739 ServiceRecord r = res.record;
11740 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011741 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011742 + r.shortName);
11743 }
11744 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011745 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011746 r.lastStartId++;
11747 if (r.lastStartId < 1) {
11748 r.lastStartId = 1;
11749 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011750 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011751 r.lastActivity = SystemClock.uptimeMillis();
11752 synchronized (r.stats.getBatteryStats()) {
11753 r.stats.startRunningLocked();
11754 }
11755 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11756 return new ComponentName("!", "Service process is bad");
11757 }
11758 return r.name;
11759 }
11760 }
11761
11762 public ComponentName startService(IApplicationThread caller, Intent service,
11763 String resolvedType) {
11764 // Refuse possible leaked file descriptors
11765 if (service != null && service.hasFileDescriptors() == true) {
11766 throw new IllegalArgumentException("File descriptors passed in Intent");
11767 }
11768
11769 synchronized(this) {
11770 final int callingPid = Binder.getCallingPid();
11771 final int callingUid = Binder.getCallingUid();
11772 final long origId = Binder.clearCallingIdentity();
11773 ComponentName res = startServiceLocked(caller, service,
11774 resolvedType, callingPid, callingUid);
11775 Binder.restoreCallingIdentity(origId);
11776 return res;
11777 }
11778 }
11779
11780 ComponentName startServiceInPackage(int uid,
11781 Intent service, String resolvedType) {
11782 synchronized(this) {
11783 final long origId = Binder.clearCallingIdentity();
11784 ComponentName res = startServiceLocked(null, service,
11785 resolvedType, -1, uid);
11786 Binder.restoreCallingIdentity(origId);
11787 return res;
11788 }
11789 }
11790
11791 public int stopService(IApplicationThread caller, Intent service,
11792 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 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011799 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011800 + " type=" + resolvedType);
11801
11802 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11803 if (caller != null && callerApp == null) {
11804 throw new SecurityException(
11805 "Unable to find app for caller " + caller
11806 + " (pid=" + Binder.getCallingPid()
11807 + ") when stopping service " + service);
11808 }
11809
11810 // If this service is active, make sure it is stopped.
11811 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11812 if (r != null) {
11813 if (r.record != null) {
11814 synchronized (r.record.stats.getBatteryStats()) {
11815 r.record.stats.stopRunningLocked();
11816 }
11817 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011818 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011819 final long origId = Binder.clearCallingIdentity();
11820 bringDownServiceLocked(r.record, false);
11821 Binder.restoreCallingIdentity(origId);
11822 return 1;
11823 }
11824 return -1;
11825 }
11826 }
11827
11828 return 0;
11829 }
11830
11831 public IBinder peekService(Intent service, String resolvedType) {
11832 // Refuse possible leaked file descriptors
11833 if (service != null && service.hasFileDescriptors() == true) {
11834 throw new IllegalArgumentException("File descriptors passed in Intent");
11835 }
11836
11837 IBinder ret = null;
11838
11839 synchronized(this) {
11840 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11841
11842 if (r != null) {
11843 // r.record is null if findServiceLocked() failed the caller permission check
11844 if (r.record == null) {
11845 throw new SecurityException(
11846 "Permission Denial: Accessing service " + r.record.name
11847 + " from pid=" + Binder.getCallingPid()
11848 + ", uid=" + Binder.getCallingUid()
11849 + " requires " + r.permission);
11850 }
11851 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11852 if (ib != null) {
11853 ret = ib.binder;
11854 }
11855 }
11856 }
11857
11858 return ret;
11859 }
11860
11861 public boolean stopServiceToken(ComponentName className, IBinder token,
11862 int startId) {
11863 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011864 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011865 + " " + token + " startId=" + startId);
11866 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011867 if (r != null) {
11868 if (startId >= 0) {
11869 // Asked to only stop if done with all work. Note that
11870 // to avoid leaks, we will take this as dropping all
11871 // start items up to and including this one.
11872 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11873 if (si != null) {
11874 while (r.deliveredStarts.size() > 0) {
11875 if (r.deliveredStarts.remove(0) == si) {
11876 break;
11877 }
11878 }
11879 }
11880
11881 if (r.lastStartId != startId) {
11882 return false;
11883 }
11884
11885 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011886 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011887 + " is last, but have " + r.deliveredStarts.size()
11888 + " remaining args");
11889 }
11890 }
11891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011892 synchronized (r.stats.getBatteryStats()) {
11893 r.stats.stopRunningLocked();
11894 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011895 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011896 }
11897 final long origId = Binder.clearCallingIdentity();
11898 bringDownServiceLocked(r, false);
11899 Binder.restoreCallingIdentity(origId);
11900 return true;
11901 }
11902 }
11903 return false;
11904 }
11905
11906 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011907 int id, Notification notification, boolean removeNotification) {
11908 final long origId = Binder.clearCallingIdentity();
11909 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011910 synchronized(this) {
11911 ServiceRecord r = findServiceLocked(className, token);
11912 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011913 if (id != 0) {
11914 if (notification == null) {
11915 throw new IllegalArgumentException("null notification");
11916 }
11917 if (r.foregroundId != id) {
11918 r.cancelNotification();
11919 r.foregroundId = id;
11920 }
11921 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11922 r.foregroundNoti = notification;
11923 r.isForeground = true;
11924 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011925 if (r.app != null) {
11926 updateServiceForegroundLocked(r.app, true);
11927 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011928 } else {
11929 if (r.isForeground) {
11930 r.isForeground = false;
11931 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011932 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011933 updateServiceForegroundLocked(r.app, true);
11934 }
11935 }
11936 if (removeNotification) {
11937 r.cancelNotification();
11938 r.foregroundId = 0;
11939 r.foregroundNoti = null;
11940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011941 }
11942 }
11943 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011944 } finally {
11945 Binder.restoreCallingIdentity(origId);
11946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011947 }
11948
11949 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11950 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070011951 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 if (sr.isForeground) {
11953 anyForeground = true;
11954 break;
11955 }
11956 }
11957 if (anyForeground != proc.foregroundServices) {
11958 proc.foregroundServices = anyForeground;
11959 if (oomAdj) {
11960 updateOomAdjLocked();
11961 }
11962 }
11963 }
11964
11965 public int bindService(IApplicationThread caller, IBinder token,
11966 Intent service, String resolvedType,
11967 IServiceConnection connection, int flags) {
11968 // Refuse possible leaked file descriptors
11969 if (service != null && service.hasFileDescriptors() == true) {
11970 throw new IllegalArgumentException("File descriptors passed in Intent");
11971 }
11972
11973 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011974 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011975 + " type=" + resolvedType + " conn=" + connection.asBinder()
11976 + " flags=0x" + Integer.toHexString(flags));
11977 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11978 if (callerApp == null) {
11979 throw new SecurityException(
11980 "Unable to find app for caller " + caller
11981 + " (pid=" + Binder.getCallingPid()
11982 + ") when binding service " + service);
11983 }
11984
11985 HistoryRecord activity = null;
11986 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011987 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011988 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011989 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011990 return 0;
11991 }
11992 activity = (HistoryRecord)mHistory.get(aindex);
11993 }
11994
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011995 int clientLabel = 0;
11996 PendingIntent clientIntent = null;
11997
11998 if (callerApp.info.uid == Process.SYSTEM_UID) {
11999 // Hacky kind of thing -- allow system stuff to tell us
12000 // what they are, so we can report this elsewhere for
12001 // others to know why certain services are running.
12002 try {
12003 clientIntent = (PendingIntent)service.getParcelableExtra(
12004 Intent.EXTRA_CLIENT_INTENT);
12005 } catch (RuntimeException e) {
12006 }
12007 if (clientIntent != null) {
12008 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
12009 if (clientLabel != 0) {
12010 // There are no useful extras in the intent, trash them.
12011 // System code calling with this stuff just needs to know
12012 // this will happen.
12013 service = service.cloneFilter();
12014 }
12015 }
12016 }
12017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012018 ServiceLookupResult res =
12019 retrieveServiceLocked(service, resolvedType,
12020 Binder.getCallingPid(), Binder.getCallingUid());
12021 if (res == null) {
12022 return 0;
12023 }
12024 if (res.record == null) {
12025 return -1;
12026 }
12027 ServiceRecord s = res.record;
12028
12029 final long origId = Binder.clearCallingIdentity();
12030
12031 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012032 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012033 + s.shortName);
12034 }
12035
12036 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
12037 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012038 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012039
12040 IBinder binder = connection.asBinder();
12041 s.connections.put(binder, c);
12042 b.connections.add(c);
12043 if (activity != null) {
12044 if (activity.connections == null) {
12045 activity.connections = new HashSet<ConnectionRecord>();
12046 }
12047 activity.connections.add(c);
12048 }
12049 b.client.connections.add(c);
12050 mServiceConnections.put(binder, c);
12051
12052 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
12053 s.lastActivity = SystemClock.uptimeMillis();
12054 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
12055 return 0;
12056 }
12057 }
12058
12059 if (s.app != null) {
12060 // This could have made the service more important.
12061 updateOomAdjLocked(s.app);
12062 }
12063
Joe Onorato8a9b2202010-02-26 18:56:32 -080012064 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012065 + ": received=" + b.intent.received
12066 + " apps=" + b.intent.apps.size()
12067 + " doRebind=" + b.intent.doRebind);
12068
12069 if (s.app != null && b.intent.received) {
12070 // Service is already running, so we can immediately
12071 // publish the connection.
12072 try {
12073 c.conn.connected(s.name, b.intent.binder);
12074 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012075 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012076 + " to connection " + c.conn.asBinder()
12077 + " (in " + c.binding.client.processName + ")", e);
12078 }
12079
12080 // If this is the first app connected back to this binding,
12081 // and the service had previously asked to be told when
12082 // rebound, then do so.
12083 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
12084 requestServiceBindingLocked(s, b.intent, true);
12085 }
12086 } else if (!b.intent.requested) {
12087 requestServiceBindingLocked(s, b.intent, false);
12088 }
12089
12090 Binder.restoreCallingIdentity(origId);
12091 }
12092
12093 return 1;
12094 }
12095
12096 private void removeConnectionLocked(
12097 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
12098 IBinder binder = c.conn.asBinder();
12099 AppBindRecord b = c.binding;
12100 ServiceRecord s = b.service;
12101 s.connections.remove(binder);
12102 b.connections.remove(c);
12103 if (c.activity != null && c.activity != skipAct) {
12104 if (c.activity.connections != null) {
12105 c.activity.connections.remove(c);
12106 }
12107 }
12108 if (b.client != skipApp) {
12109 b.client.connections.remove(c);
12110 }
12111 mServiceConnections.remove(binder);
12112
12113 if (b.connections.size() == 0) {
12114 b.intent.apps.remove(b.client);
12115 }
12116
Joe Onorato8a9b2202010-02-26 18:56:32 -080012117 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012118 + ": shouldUnbind=" + b.intent.hasBound);
12119 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
12120 && b.intent.hasBound) {
12121 try {
12122 bumpServiceExecutingLocked(s);
12123 updateOomAdjLocked(s.app);
12124 b.intent.hasBound = false;
12125 // Assume the client doesn't want to know about a rebind;
12126 // we will deal with that later if it asks for one.
12127 b.intent.doRebind = false;
12128 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
12129 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012130 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012131 serviceDoneExecutingLocked(s, true);
12132 }
12133 }
12134
12135 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
12136 bringDownServiceLocked(s, false);
12137 }
12138 }
12139
12140 public boolean unbindService(IServiceConnection connection) {
12141 synchronized (this) {
12142 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012143 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012144 ConnectionRecord r = mServiceConnections.get(binder);
12145 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012146 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012147 + connection.asBinder());
12148 return false;
12149 }
12150
12151 final long origId = Binder.clearCallingIdentity();
12152
12153 removeConnectionLocked(r, null, null);
12154
12155 if (r.binding.service.app != null) {
12156 // This could have made the service less important.
12157 updateOomAdjLocked(r.binding.service.app);
12158 }
12159
12160 Binder.restoreCallingIdentity(origId);
12161 }
12162
12163 return true;
12164 }
12165
12166 public void publishService(IBinder token, Intent intent, IBinder service) {
12167 // Refuse possible leaked file descriptors
12168 if (intent != null && intent.hasFileDescriptors() == true) {
12169 throw new IllegalArgumentException("File descriptors passed in Intent");
12170 }
12171
12172 synchronized(this) {
12173 if (!(token instanceof ServiceRecord)) {
12174 throw new IllegalArgumentException("Invalid service token");
12175 }
12176 ServiceRecord r = (ServiceRecord)token;
12177
12178 final long origId = Binder.clearCallingIdentity();
12179
Joe Onorato8a9b2202010-02-26 18:56:32 -080012180 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012181 + " " + intent + ": " + service);
12182 if (r != null) {
12183 Intent.FilterComparison filter
12184 = new Intent.FilterComparison(intent);
12185 IntentBindRecord b = r.bindings.get(filter);
12186 if (b != null && !b.received) {
12187 b.binder = service;
12188 b.requested = true;
12189 b.received = true;
12190 if (r.connections.size() > 0) {
12191 Iterator<ConnectionRecord> it
12192 = r.connections.values().iterator();
12193 while (it.hasNext()) {
12194 ConnectionRecord c = it.next();
12195 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012196 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012197 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012198 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012199 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012200 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012201 TAG, "Published intent: " + intent);
12202 continue;
12203 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012204 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012205 try {
12206 c.conn.connected(r.name, service);
12207 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012208 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012209 " to connection " + c.conn.asBinder() +
12210 " (in " + c.binding.client.processName + ")", e);
12211 }
12212 }
12213 }
12214 }
12215
12216 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12217
12218 Binder.restoreCallingIdentity(origId);
12219 }
12220 }
12221 }
12222
12223 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
12224 // Refuse possible leaked file descriptors
12225 if (intent != null && intent.hasFileDescriptors() == true) {
12226 throw new IllegalArgumentException("File descriptors passed in Intent");
12227 }
12228
12229 synchronized(this) {
12230 if (!(token instanceof ServiceRecord)) {
12231 throw new IllegalArgumentException("Invalid service token");
12232 }
12233 ServiceRecord r = (ServiceRecord)token;
12234
12235 final long origId = Binder.clearCallingIdentity();
12236
12237 if (r != null) {
12238 Intent.FilterComparison filter
12239 = new Intent.FilterComparison(intent);
12240 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012241 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012242 + " at " + b + ": apps="
12243 + (b != null ? b.apps.size() : 0));
12244 if (b != null) {
12245 if (b.apps.size() > 0) {
12246 // Applications have already bound since the last
12247 // unbind, so just rebind right here.
12248 requestServiceBindingLocked(r, b, true);
12249 } else {
12250 // Note to tell the service the next time there is
12251 // a new client.
12252 b.doRebind = true;
12253 }
12254 }
12255
12256 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12257
12258 Binder.restoreCallingIdentity(origId);
12259 }
12260 }
12261 }
12262
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012263 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012264 synchronized(this) {
12265 if (!(token instanceof ServiceRecord)) {
12266 throw new IllegalArgumentException("Invalid service token");
12267 }
12268 ServiceRecord r = (ServiceRecord)token;
12269 boolean inStopping = mStoppingServices.contains(token);
12270 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012271 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012272 + ": nesting=" + r.executeNesting
12273 + ", inStopping=" + inStopping);
12274 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012275 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012276 + " with incorrect token: given " + token
12277 + ", expected " + r);
12278 return;
12279 }
12280
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012281 if (type == 1) {
12282 // This is a call from a service start... take care of
12283 // book-keeping.
12284 r.callStart = true;
12285 switch (res) {
12286 case Service.START_STICKY_COMPATIBILITY:
12287 case Service.START_STICKY: {
12288 // We are done with the associated start arguments.
12289 r.findDeliveredStart(startId, true);
12290 // Don't stop if killed.
12291 r.stopIfKilled = false;
12292 break;
12293 }
12294 case Service.START_NOT_STICKY: {
12295 // We are done with the associated start arguments.
12296 r.findDeliveredStart(startId, true);
12297 if (r.lastStartId == startId) {
12298 // There is no more work, and this service
12299 // doesn't want to hang around if killed.
12300 r.stopIfKilled = true;
12301 }
12302 break;
12303 }
12304 case Service.START_REDELIVER_INTENT: {
12305 // We'll keep this item until they explicitly
12306 // call stop for it, but keep track of the fact
12307 // that it was delivered.
12308 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12309 if (si != null) {
12310 si.deliveryCount = 0;
12311 si.doneExecutingCount++;
12312 // Don't stop if killed.
12313 r.stopIfKilled = true;
12314 }
12315 break;
12316 }
12317 default:
12318 throw new IllegalArgumentException(
12319 "Unknown service start result: " + res);
12320 }
12321 if (res == Service.START_STICKY_COMPATIBILITY) {
12322 r.callStart = false;
12323 }
12324 }
12325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012326 final long origId = Binder.clearCallingIdentity();
12327 serviceDoneExecutingLocked(r, inStopping);
12328 Binder.restoreCallingIdentity(origId);
12329 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012330 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012331 + " with token " + token);
12332 }
12333 }
12334 }
12335
12336 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
12337 r.executeNesting--;
12338 if (r.executeNesting <= 0 && r.app != null) {
12339 r.app.executingServices.remove(r);
12340 if (r.app.executingServices.size() == 0) {
12341 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
12342 }
12343 if (inStopping) {
12344 mStoppingServices.remove(r);
12345 }
12346 updateOomAdjLocked(r.app);
12347 }
12348 }
12349
12350 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012351 String anrMessage = null;
12352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012353 synchronized(this) {
12354 if (proc.executingServices.size() == 0 || proc.thread == null) {
12355 return;
12356 }
12357 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12358 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12359 ServiceRecord timeout = null;
12360 long nextTime = 0;
12361 while (it.hasNext()) {
12362 ServiceRecord sr = it.next();
12363 if (sr.executingStart < maxTime) {
12364 timeout = sr;
12365 break;
12366 }
12367 if (sr.executingStart > nextTime) {
12368 nextTime = sr.executingStart;
12369 }
12370 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012371 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012372 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012373 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012374 } else {
12375 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12376 msg.obj = proc;
12377 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12378 }
12379 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012380
12381 if (anrMessage != null) {
12382 appNotResponding(proc, null, null, anrMessage);
12383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012384 }
12385
12386 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012387 // BACKUP AND RESTORE
12388 // =========================================================
12389
12390 // Cause the target app to be launched if necessary and its backup agent
12391 // instantiated. The backup agent will invoke backupAgentCreated() on the
12392 // activity manager to announce its creation.
12393 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012394 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012395 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12396
12397 synchronized(this) {
12398 // !!! TODO: currently no check here that we're already bound
12399 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12400 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12401 synchronized (stats) {
12402 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12403 }
12404
12405 BackupRecord r = new BackupRecord(ss, app, backupMode);
12406 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12407 // startProcessLocked() returns existing proc's record if it's already running
12408 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012409 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012410 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012411 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012412 return false;
12413 }
12414
12415 r.app = proc;
12416 mBackupTarget = r;
12417 mBackupAppName = app.packageName;
12418
Christopher Tate6fa95972009-06-05 18:43:55 -070012419 // Try not to kill the process during backup
12420 updateOomAdjLocked(proc);
12421
Christopher Tate181fafa2009-05-14 11:12:14 -070012422 // If the process is already attached, schedule the creation of the backup agent now.
12423 // If it is not yet live, this will be done when it attaches to the framework.
12424 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012425 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012426 try {
12427 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12428 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012429 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012430 }
12431 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012432 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012433 }
12434 // Invariants: at this point, the target app process exists and the application
12435 // is either already running or in the process of coming up. mBackupTarget and
12436 // mBackupAppName describe the app, so that when it binds back to the AM we
12437 // know that it's scheduled for a backup-agent operation.
12438 }
12439
12440 return true;
12441 }
12442
12443 // A backup agent has just come up
12444 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012445 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012446 + " = " + agent);
12447
12448 synchronized(this) {
12449 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012450 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012451 return;
12452 }
12453
Christopher Tate043dadc2009-06-02 16:11:00 -070012454 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012455 try {
12456 IBackupManager bm = IBackupManager.Stub.asInterface(
12457 ServiceManager.getService(Context.BACKUP_SERVICE));
12458 bm.agentConnected(agentPackageName, agent);
12459 } catch (RemoteException e) {
12460 // can't happen; the backup manager service is local
12461 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012462 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012463 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012464 } finally {
12465 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012466 }
12467 }
12468 }
12469
12470 // done with this agent
12471 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012472 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012473 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012474 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012475 return;
12476 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012477
12478 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012479 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012480 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012481 return;
12482 }
12483
Christopher Tate181fafa2009-05-14 11:12:14 -070012484 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012485 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012486 return;
12487 }
12488
Christopher Tate6fa95972009-06-05 18:43:55 -070012489 ProcessRecord proc = mBackupTarget.app;
12490 mBackupTarget = null;
12491 mBackupAppName = null;
12492
12493 // Not backing this app up any more; reset its OOM adjustment
12494 updateOomAdjLocked(proc);
12495
Christopher Tatec7b31e32009-06-10 15:49:30 -070012496 // If the app crashed during backup, 'thread' will be null here
12497 if (proc.thread != null) {
12498 try {
12499 proc.thread.scheduleDestroyBackupAgent(appInfo);
12500 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012501 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012502 e.printStackTrace();
12503 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012504 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012505 }
12506 }
12507 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012508 // BROADCASTS
12509 // =========================================================
12510
Josh Bartel7f208742010-02-25 11:01:44 -060012511 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012512 List cur) {
12513 final ContentResolver resolver = mContext.getContentResolver();
12514 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12515 if (list == null) {
12516 return cur;
12517 }
12518 int N = list.size();
12519 for (int i=0; i<N; i++) {
12520 Intent intent = list.get(i);
12521 if (filter.match(resolver, intent, true, TAG) >= 0) {
12522 if (cur == null) {
12523 cur = new ArrayList<Intent>();
12524 }
12525 cur.add(intent);
12526 }
12527 }
12528 return cur;
12529 }
12530
12531 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012532 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012533 + mBroadcastsScheduled);
12534
12535 if (mBroadcastsScheduled) {
12536 return;
12537 }
12538 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12539 mBroadcastsScheduled = true;
12540 }
12541
12542 public Intent registerReceiver(IApplicationThread caller,
12543 IIntentReceiver receiver, IntentFilter filter, String permission) {
12544 synchronized(this) {
12545 ProcessRecord callerApp = null;
12546 if (caller != null) {
12547 callerApp = getRecordForAppLocked(caller);
12548 if (callerApp == null) {
12549 throw new SecurityException(
12550 "Unable to find app for caller " + caller
12551 + " (pid=" + Binder.getCallingPid()
12552 + ") when registering receiver " + receiver);
12553 }
12554 }
12555
12556 List allSticky = null;
12557
12558 // Look for any matching sticky broadcasts...
12559 Iterator actions = filter.actionsIterator();
12560 if (actions != null) {
12561 while (actions.hasNext()) {
12562 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012563 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012564 }
12565 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012566 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012567 }
12568
12569 // The first sticky in the list is returned directly back to
12570 // the client.
12571 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12572
Joe Onorato8a9b2202010-02-26 18:56:32 -080012573 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012574 + ": " + sticky);
12575
12576 if (receiver == null) {
12577 return sticky;
12578 }
12579
12580 ReceiverList rl
12581 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12582 if (rl == null) {
12583 rl = new ReceiverList(this, callerApp,
12584 Binder.getCallingPid(),
12585 Binder.getCallingUid(), receiver);
12586 if (rl.app != null) {
12587 rl.app.receivers.add(rl);
12588 } else {
12589 try {
12590 receiver.asBinder().linkToDeath(rl, 0);
12591 } catch (RemoteException e) {
12592 return sticky;
12593 }
12594 rl.linkedToDeath = true;
12595 }
12596 mRegisteredReceivers.put(receiver.asBinder(), rl);
12597 }
12598 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12599 rl.add(bf);
12600 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012601 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012602 }
12603 mReceiverResolver.addFilter(bf);
12604
12605 // Enqueue broadcasts for all existing stickies that match
12606 // this filter.
12607 if (allSticky != null) {
12608 ArrayList receivers = new ArrayList();
12609 receivers.add(bf);
12610
12611 int N = allSticky.size();
12612 for (int i=0; i<N; i++) {
12613 Intent intent = (Intent)allSticky.get(i);
12614 BroadcastRecord r = new BroadcastRecord(intent, null,
12615 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012616 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012617 if (mParallelBroadcasts.size() == 0) {
12618 scheduleBroadcastsLocked();
12619 }
12620 mParallelBroadcasts.add(r);
12621 }
12622 }
12623
12624 return sticky;
12625 }
12626 }
12627
12628 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012629 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012630
12631 boolean doNext = false;
12632
12633 synchronized(this) {
12634 ReceiverList rl
12635 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12636 if (rl != null) {
12637 if (rl.curBroadcast != null) {
12638 BroadcastRecord r = rl.curBroadcast;
12639 doNext = finishReceiverLocked(
12640 receiver.asBinder(), r.resultCode, r.resultData,
12641 r.resultExtras, r.resultAbort, true);
12642 }
12643
12644 if (rl.app != null) {
12645 rl.app.receivers.remove(rl);
12646 }
12647 removeReceiverLocked(rl);
12648 if (rl.linkedToDeath) {
12649 rl.linkedToDeath = false;
12650 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12651 }
12652 }
12653 }
12654
12655 if (!doNext) {
12656 return;
12657 }
12658
12659 final long origId = Binder.clearCallingIdentity();
12660 processNextBroadcast(false);
12661 trimApplications();
12662 Binder.restoreCallingIdentity(origId);
12663 }
12664
12665 void removeReceiverLocked(ReceiverList rl) {
12666 mRegisteredReceivers.remove(rl.receiver.asBinder());
12667 int N = rl.size();
12668 for (int i=0; i<N; i++) {
12669 mReceiverResolver.removeFilter(rl.get(i));
12670 }
12671 }
12672
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012673 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12674 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12675 ProcessRecord r = mLruProcesses.get(i);
12676 if (r.thread != null) {
12677 try {
12678 r.thread.dispatchPackageBroadcast(cmd, packages);
12679 } catch (RemoteException ex) {
12680 }
12681 }
12682 }
12683 }
12684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012685 private final int broadcastIntentLocked(ProcessRecord callerApp,
12686 String callerPackage, Intent intent, String resolvedType,
12687 IIntentReceiver resultTo, int resultCode, String resultData,
12688 Bundle map, String requiredPermission,
12689 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12690 intent = new Intent(intent);
12691
Joe Onorato8a9b2202010-02-26 18:56:32 -080012692 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012693 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12694 + " ordered=" + ordered);
12695 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012696 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012697 }
12698
12699 // Handle special intents: if this broadcast is from the package
12700 // manager about a package being removed, we need to remove all of
12701 // its activities from the history stack.
12702 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12703 intent.getAction());
12704 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12705 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012706 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012707 || uidRemoved) {
12708 if (checkComponentPermission(
12709 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12710 callingPid, callingUid, -1)
12711 == PackageManager.PERMISSION_GRANTED) {
12712 if (uidRemoved) {
12713 final Bundle intentExtras = intent.getExtras();
12714 final int uid = intentExtras != null
12715 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12716 if (uid >= 0) {
12717 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12718 synchronized (bs) {
12719 bs.removeUidStatsLocked(uid);
12720 }
12721 }
12722 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012723 // If resources are unvailble just force stop all
12724 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012725 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012726 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12727 if (list != null && (list.length > 0)) {
12728 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012729 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012730 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012731 sendPackageBroadcastLocked(
12732 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012733 }
12734 } else {
12735 Uri data = intent.getData();
12736 String ssp;
12737 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12738 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12739 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012740 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012741 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012742 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
12743 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12744 new String[] {ssp});
12745 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012746 }
12747 }
12748 }
12749 } else {
12750 String msg = "Permission Denial: " + intent.getAction()
12751 + " broadcast from " + callerPackage + " (pid=" + callingPid
12752 + ", uid=" + callingUid + ")"
12753 + " requires "
12754 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012755 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012756 throw new SecurityException(msg);
12757 }
12758 }
12759
12760 /*
12761 * If this is the time zone changed action, queue up a message that will reset the timezone
12762 * of all currently running processes. This message will get queued up before the broadcast
12763 * happens.
12764 */
12765 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12766 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12767 }
12768
Dianne Hackborn854060af2009-07-09 18:14:31 -070012769 /*
12770 * Prevent non-system code (defined here to be non-persistent
12771 * processes) from sending protected broadcasts.
12772 */
12773 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12774 || callingUid == Process.SHELL_UID || callingUid == 0) {
12775 // Always okay.
12776 } else if (callerApp == null || !callerApp.persistent) {
12777 try {
12778 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12779 intent.getAction())) {
12780 String msg = "Permission Denial: not allowed to send broadcast "
12781 + intent.getAction() + " from pid="
12782 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012783 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012784 throw new SecurityException(msg);
12785 }
12786 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012787 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012788 return BROADCAST_SUCCESS;
12789 }
12790 }
12791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012792 // Add to the sticky list if requested.
12793 if (sticky) {
12794 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12795 callingPid, callingUid)
12796 != PackageManager.PERMISSION_GRANTED) {
12797 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12798 + callingPid + ", uid=" + callingUid
12799 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012800 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012801 throw new SecurityException(msg);
12802 }
12803 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012804 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012805 + " and enforce permission " + requiredPermission);
12806 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12807 }
12808 if (intent.getComponent() != null) {
12809 throw new SecurityException(
12810 "Sticky broadcasts can't target a specific component");
12811 }
12812 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12813 if (list == null) {
12814 list = new ArrayList<Intent>();
12815 mStickyBroadcasts.put(intent.getAction(), list);
12816 }
12817 int N = list.size();
12818 int i;
12819 for (i=0; i<N; i++) {
12820 if (intent.filterEquals(list.get(i))) {
12821 // This sticky already exists, replace it.
12822 list.set(i, new Intent(intent));
12823 break;
12824 }
12825 }
12826 if (i >= N) {
12827 list.add(new Intent(intent));
12828 }
12829 }
12830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012831 // Figure out who all will receive this broadcast.
12832 List receivers = null;
12833 List<BroadcastFilter> registeredReceivers = null;
12834 try {
12835 if (intent.getComponent() != null) {
12836 // Broadcast is going to one specific receiver class...
12837 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012838 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012839 if (ai != null) {
12840 receivers = new ArrayList();
12841 ResolveInfo ri = new ResolveInfo();
12842 ri.activityInfo = ai;
12843 receivers.add(ri);
12844 }
12845 } else {
12846 // Need to resolve the intent to interested receivers...
12847 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12848 == 0) {
12849 receivers =
12850 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012851 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012852 }
Mihai Preda074edef2009-05-18 17:13:31 +020012853 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012854 }
12855 } catch (RemoteException ex) {
12856 // pm is in same process, this will never happen.
12857 }
12858
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012859 final boolean replacePending =
12860 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12861
Joe Onorato8a9b2202010-02-26 18:56:32 -080012862 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012863 + " replacePending=" + replacePending);
12864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012865 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12866 if (!ordered && NR > 0) {
12867 // If we are not serializing this broadcast, then send the
12868 // registered receivers separately so they don't wait for the
12869 // components to be launched.
12870 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12871 callerPackage, callingPid, callingUid, requiredPermission,
12872 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012873 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012874 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012875 TAG, "Enqueueing parallel broadcast " + r
12876 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012877 boolean replaced = false;
12878 if (replacePending) {
12879 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12880 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012881 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012882 "***** DROPPING PARALLEL: " + intent);
12883 mParallelBroadcasts.set(i, r);
12884 replaced = true;
12885 break;
12886 }
12887 }
12888 }
12889 if (!replaced) {
12890 mParallelBroadcasts.add(r);
12891 scheduleBroadcastsLocked();
12892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012893 registeredReceivers = null;
12894 NR = 0;
12895 }
12896
12897 // Merge into one list.
12898 int ir = 0;
12899 if (receivers != null) {
12900 // A special case for PACKAGE_ADDED: do not allow the package
12901 // being added to see this broadcast. This prevents them from
12902 // using this as a back door to get run as soon as they are
12903 // installed. Maybe in the future we want to have a special install
12904 // broadcast or such for apps, but we'd like to deliberately make
12905 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012906 String skipPackages[] = null;
12907 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12908 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12909 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12910 Uri data = intent.getData();
12911 if (data != null) {
12912 String pkgName = data.getSchemeSpecificPart();
12913 if (pkgName != null) {
12914 skipPackages = new String[] { pkgName };
12915 }
12916 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012917 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012918 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012919 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012920 if (skipPackages != null && (skipPackages.length > 0)) {
12921 for (String skipPackage : skipPackages) {
12922 if (skipPackage != null) {
12923 int NT = receivers.size();
12924 for (int it=0; it<NT; it++) {
12925 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12926 if (curt.activityInfo.packageName.equals(skipPackage)) {
12927 receivers.remove(it);
12928 it--;
12929 NT--;
12930 }
12931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012932 }
12933 }
12934 }
12935
12936 int NT = receivers != null ? receivers.size() : 0;
12937 int it = 0;
12938 ResolveInfo curt = null;
12939 BroadcastFilter curr = null;
12940 while (it < NT && ir < NR) {
12941 if (curt == null) {
12942 curt = (ResolveInfo)receivers.get(it);
12943 }
12944 if (curr == null) {
12945 curr = registeredReceivers.get(ir);
12946 }
12947 if (curr.getPriority() >= curt.priority) {
12948 // Insert this broadcast record into the final list.
12949 receivers.add(it, curr);
12950 ir++;
12951 curr = null;
12952 it++;
12953 NT++;
12954 } else {
12955 // Skip to the next ResolveInfo in the final list.
12956 it++;
12957 curt = null;
12958 }
12959 }
12960 }
12961 while (ir < NR) {
12962 if (receivers == null) {
12963 receivers = new ArrayList();
12964 }
12965 receivers.add(registeredReceivers.get(ir));
12966 ir++;
12967 }
12968
12969 if ((receivers != null && receivers.size() > 0)
12970 || resultTo != null) {
12971 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12972 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012973 receivers, resultTo, resultCode, resultData, map, ordered,
12974 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012975 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012976 TAG, "Enqueueing ordered broadcast " + r
12977 + ": prev had " + mOrderedBroadcasts.size());
12978 if (DEBUG_BROADCAST) {
12979 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012980 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012981 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012982 boolean replaced = false;
12983 if (replacePending) {
12984 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12985 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012986 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012987 "***** DROPPING ORDERED: " + intent);
12988 mOrderedBroadcasts.set(i, r);
12989 replaced = true;
12990 break;
12991 }
12992 }
12993 }
12994 if (!replaced) {
12995 mOrderedBroadcasts.add(r);
12996 scheduleBroadcastsLocked();
12997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012998 }
12999
13000 return BROADCAST_SUCCESS;
13001 }
13002
13003 public final int broadcastIntent(IApplicationThread caller,
13004 Intent intent, String resolvedType, IIntentReceiver resultTo,
13005 int resultCode, String resultData, Bundle map,
13006 String requiredPermission, boolean serialized, boolean sticky) {
13007 // Refuse possible leaked file descriptors
13008 if (intent != null && intent.hasFileDescriptors() == true) {
13009 throw new IllegalArgumentException("File descriptors passed in Intent");
13010 }
13011
13012 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013013 int flags = intent.getFlags();
13014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013015 if (!mSystemReady) {
13016 // if the caller really truly claims to know what they're doing, go
13017 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013018 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
13019 intent = new Intent(intent);
13020 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
13021 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080013022 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013023 + " before boot completion");
13024 throw new IllegalStateException("Cannot broadcast before boot completed");
13025 }
13026 }
13027
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013028 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
13029 throw new IllegalArgumentException(
13030 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
13031 }
13032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013033 final ProcessRecord callerApp = getRecordForAppLocked(caller);
13034 final int callingPid = Binder.getCallingPid();
13035 final int callingUid = Binder.getCallingUid();
13036 final long origId = Binder.clearCallingIdentity();
13037 int res = broadcastIntentLocked(callerApp,
13038 callerApp != null ? callerApp.info.packageName : null,
13039 intent, resolvedType, resultTo,
13040 resultCode, resultData, map, requiredPermission, serialized,
13041 sticky, callingPid, callingUid);
13042 Binder.restoreCallingIdentity(origId);
13043 return res;
13044 }
13045 }
13046
13047 int broadcastIntentInPackage(String packageName, int uid,
13048 Intent intent, String resolvedType, IIntentReceiver resultTo,
13049 int resultCode, String resultData, Bundle map,
13050 String requiredPermission, boolean serialized, boolean sticky) {
13051 synchronized(this) {
13052 final long origId = Binder.clearCallingIdentity();
13053 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
13054 resultTo, resultCode, resultData, map, requiredPermission,
13055 serialized, sticky, -1, uid);
13056 Binder.restoreCallingIdentity(origId);
13057 return res;
13058 }
13059 }
13060
13061 public final void unbroadcastIntent(IApplicationThread caller,
13062 Intent intent) {
13063 // Refuse possible leaked file descriptors
13064 if (intent != null && intent.hasFileDescriptors() == true) {
13065 throw new IllegalArgumentException("File descriptors passed in Intent");
13066 }
13067
13068 synchronized(this) {
13069 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
13070 != PackageManager.PERMISSION_GRANTED) {
13071 String msg = "Permission Denial: unbroadcastIntent() from pid="
13072 + Binder.getCallingPid()
13073 + ", uid=" + Binder.getCallingUid()
13074 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013075 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013076 throw new SecurityException(msg);
13077 }
13078 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
13079 if (list != null) {
13080 int N = list.size();
13081 int i;
13082 for (i=0; i<N; i++) {
13083 if (intent.filterEquals(list.get(i))) {
13084 list.remove(i);
13085 break;
13086 }
13087 }
13088 }
13089 }
13090 }
13091
13092 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
13093 String resultData, Bundle resultExtras, boolean resultAbort,
13094 boolean explicit) {
13095 if (mOrderedBroadcasts.size() == 0) {
13096 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013097 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013098 }
13099 return false;
13100 }
13101 BroadcastRecord r = mOrderedBroadcasts.get(0);
13102 if (r.receiver == null) {
13103 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013104 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013105 }
13106 return false;
13107 }
13108 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013109 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013110 return false;
13111 }
13112 int state = r.state;
13113 r.state = r.IDLE;
13114 if (state == r.IDLE) {
13115 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013116 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013117 }
13118 }
13119 r.receiver = null;
13120 r.intent.setComponent(null);
13121 if (r.curApp != null) {
13122 r.curApp.curReceiver = null;
13123 }
13124 if (r.curFilter != null) {
13125 r.curFilter.receiverList.curBroadcast = null;
13126 }
13127 r.curFilter = null;
13128 r.curApp = null;
13129 r.curComponent = null;
13130 r.curReceiver = null;
13131 mPendingBroadcast = null;
13132
13133 r.resultCode = resultCode;
13134 r.resultData = resultData;
13135 r.resultExtras = resultExtras;
13136 r.resultAbort = resultAbort;
13137
13138 // We will process the next receiver right now if this is finishing
13139 // an app receiver (which is always asynchronous) or after we have
13140 // come back from calling a receiver.
13141 return state == BroadcastRecord.APP_RECEIVE
13142 || state == BroadcastRecord.CALL_DONE_RECEIVE;
13143 }
13144
13145 public void finishReceiver(IBinder who, int resultCode, String resultData,
13146 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013147 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013148
13149 // Refuse possible leaked file descriptors
13150 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
13151 throw new IllegalArgumentException("File descriptors passed in Bundle");
13152 }
13153
13154 boolean doNext;
13155
13156 final long origId = Binder.clearCallingIdentity();
13157
13158 synchronized(this) {
13159 doNext = finishReceiverLocked(
13160 who, resultCode, resultData, resultExtras, resultAbort, true);
13161 }
13162
13163 if (doNext) {
13164 processNextBroadcast(false);
13165 }
13166 trimApplications();
13167
13168 Binder.restoreCallingIdentity(origId);
13169 }
13170
13171 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
13172 if (r.nextReceiver > 0) {
13173 Object curReceiver = r.receivers.get(r.nextReceiver-1);
13174 if (curReceiver instanceof BroadcastFilter) {
13175 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080013176 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013177 System.identityHashCode(r),
13178 r.intent.getAction(),
13179 r.nextReceiver - 1,
13180 System.identityHashCode(bf));
13181 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080013182 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013183 System.identityHashCode(r),
13184 r.intent.getAction(),
13185 r.nextReceiver - 1,
13186 ((ResolveInfo)curReceiver).toString());
13187 }
13188 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013189 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013190 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013191 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013192 System.identityHashCode(r),
13193 r.intent.getAction(),
13194 r.nextReceiver,
13195 "NONE");
13196 }
13197 }
13198
13199 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013200 ProcessRecord app = null;
13201 String anrMessage = null;
13202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013203 synchronized (this) {
13204 if (mOrderedBroadcasts.size() == 0) {
13205 return;
13206 }
13207 long now = SystemClock.uptimeMillis();
13208 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013209 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013210 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013211 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013212 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013213 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013214 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013215 return;
13216 }
13217
Joe Onorato8a9b2202010-02-26 18:56:32 -080013218 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013219 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013220 r.anrCount++;
13221
13222 // Current receiver has passed its expiration date.
13223 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013224 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013225 return;
13226 }
13227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013228 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013229 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013230 logBroadcastReceiverDiscard(r);
13231 if (curReceiver instanceof BroadcastFilter) {
13232 BroadcastFilter bf = (BroadcastFilter)curReceiver;
13233 if (bf.receiverList.pid != 0
13234 && bf.receiverList.pid != MY_PID) {
13235 synchronized (this.mPidsSelfLocked) {
13236 app = this.mPidsSelfLocked.get(
13237 bf.receiverList.pid);
13238 }
13239 }
13240 } else {
13241 app = r.curApp;
13242 }
13243
13244 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013245 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013246 }
13247
13248 if (mPendingBroadcast == r) {
13249 mPendingBroadcast = null;
13250 }
13251
13252 // Move on to the next receiver.
13253 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13254 r.resultExtras, r.resultAbort, true);
13255 scheduleBroadcastsLocked();
13256 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013257
13258 if (anrMessage != null) {
13259 appNotResponding(app, null, null, anrMessage);
13260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013261 }
13262
13263 private final void processCurBroadcastLocked(BroadcastRecord r,
13264 ProcessRecord app) throws RemoteException {
13265 if (app.thread == null) {
13266 throw new RemoteException();
13267 }
13268 r.receiver = app.thread.asBinder();
13269 r.curApp = app;
13270 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013271 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013272
13273 // Tell the application to launch this receiver.
13274 r.intent.setComponent(r.curComponent);
13275
13276 boolean started = false;
13277 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013278 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013279 "Delivering to component " + r.curComponent
13280 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070013281 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013282 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
13283 r.resultCode, r.resultData, r.resultExtras, r.ordered);
13284 started = true;
13285 } finally {
13286 if (!started) {
13287 r.receiver = null;
13288 r.curApp = null;
13289 app.curReceiver = null;
13290 }
13291 }
13292
13293 }
13294
13295 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013296 Intent intent, int resultCode, String data, Bundle extras,
13297 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013298 if (app != null && app.thread != null) {
13299 // If we have an app thread, do the call through that so it is
13300 // correctly ordered with other one-way calls.
13301 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013302 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013303 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013304 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013305 }
13306 }
13307
13308 private final void deliverToRegisteredReceiver(BroadcastRecord r,
13309 BroadcastFilter filter, boolean ordered) {
13310 boolean skip = false;
13311 if (filter.requiredPermission != null) {
13312 int perm = checkComponentPermission(filter.requiredPermission,
13313 r.callingPid, r.callingUid, -1);
13314 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013315 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013316 + r.intent.toString()
13317 + " from " + r.callerPackage + " (pid="
13318 + r.callingPid + ", uid=" + r.callingUid + ")"
13319 + " requires " + filter.requiredPermission
13320 + " due to registered receiver " + filter);
13321 skip = true;
13322 }
13323 }
13324 if (r.requiredPermission != null) {
13325 int perm = checkComponentPermission(r.requiredPermission,
13326 filter.receiverList.pid, filter.receiverList.uid, -1);
13327 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013328 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013329 + r.intent.toString()
13330 + " to " + filter.receiverList.app
13331 + " (pid=" + filter.receiverList.pid
13332 + ", uid=" + filter.receiverList.uid + ")"
13333 + " requires " + r.requiredPermission
13334 + " due to sender " + r.callerPackage
13335 + " (uid " + r.callingUid + ")");
13336 skip = true;
13337 }
13338 }
13339
13340 if (!skip) {
13341 // If this is not being sent as an ordered broadcast, then we
13342 // don't want to touch the fields that keep track of the current
13343 // state of ordered broadcasts.
13344 if (ordered) {
13345 r.receiver = filter.receiverList.receiver.asBinder();
13346 r.curFilter = filter;
13347 filter.receiverList.curBroadcast = r;
13348 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013349 if (filter.receiverList.app != null) {
13350 // Bump hosting application to no longer be in background
13351 // scheduling class. Note that we can't do that if there
13352 // isn't an app... but we can only be in that case for
13353 // things that directly call the IActivityManager API, which
13354 // are already core system stuff so don't matter for this.
13355 r.curApp = filter.receiverList.app;
13356 filter.receiverList.app.curReceiver = r;
13357 updateOomAdjLocked();
13358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013359 }
13360 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013361 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013362 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013363 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013364 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013365 }
13366 performReceive(filter.receiverList.app, filter.receiverList.receiver,
13367 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013368 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013369 if (ordered) {
13370 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13371 }
13372 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013373 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013374 if (ordered) {
13375 r.receiver = null;
13376 r.curFilter = null;
13377 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013378 if (filter.receiverList.app != null) {
13379 filter.receiverList.app.curReceiver = null;
13380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381 }
13382 }
13383 }
13384 }
13385
Dianne Hackborn12527f92009-11-11 17:39:50 -080013386 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13387 if (r.callingUid < 0) {
13388 // This was from a registerReceiver() call; ignore it.
13389 return;
13390 }
13391 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13392 MAX_BROADCAST_HISTORY-1);
13393 r.finishTime = SystemClock.uptimeMillis();
13394 mBroadcastHistory[0] = r;
13395 }
13396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013397 private final void processNextBroadcast(boolean fromMsg) {
13398 synchronized(this) {
13399 BroadcastRecord r;
13400
Joe Onorato8a9b2202010-02-26 18:56:32 -080013401 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013402 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013403 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013404
13405 updateCpuStats();
13406
13407 if (fromMsg) {
13408 mBroadcastsScheduled = false;
13409 }
13410
13411 // First, deliver any non-serialized broadcasts right away.
13412 while (mParallelBroadcasts.size() > 0) {
13413 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013414 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013415 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013416 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013417 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013418 for (int i=0; i<N; i++) {
13419 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013420 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013421 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013422 + target + ": " + r);
13423 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13424 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013425 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013426 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013427 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013428 }
13429
13430 // Now take care of the next serialized one...
13431
13432 // If we are waiting for a process to come up to handle the next
13433 // broadcast, then do nothing at this point. Just in case, we
13434 // check that the process we're waiting for still exists.
13435 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013436 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013437 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013438 + mPendingBroadcast.curApp);
13439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013440
13441 boolean isDead;
13442 synchronized (mPidsSelfLocked) {
13443 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13444 }
13445 if (!isDead) {
13446 // It's still alive, so keep waiting
13447 return;
13448 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013449 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013450 + " died before responding to broadcast");
13451 mPendingBroadcast = null;
13452 }
13453 }
13454
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013455 boolean looped = false;
13456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013457 do {
13458 if (mOrderedBroadcasts.size() == 0) {
13459 // No more broadcasts pending, so all done!
13460 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013461 if (looped) {
13462 // If we had finished the last ordered broadcast, then
13463 // make sure all processes have correct oom and sched
13464 // adjustments.
13465 updateOomAdjLocked();
13466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013467 return;
13468 }
13469 r = mOrderedBroadcasts.get(0);
13470 boolean forceReceive = false;
13471
13472 // Ensure that even if something goes awry with the timeout
13473 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013474 // and continue to make progress.
13475 //
13476 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
13477 // receivers don't get executed with with timeouts. They're intended for
13478 // one time heavy lifting after system upgrades and can take
13479 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013480 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013481 if (mSystemReady && r.dispatchTime > 0) {
13482 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013483 if ((numReceivers > 0) &&
13484 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013485 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013486 + " now=" + now
13487 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013488 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013489 + " intent=" + r.intent
13490 + " numReceivers=" + numReceivers
13491 + " nextReceiver=" + r.nextReceiver
13492 + " state=" + r.state);
13493 broadcastTimeout(); // forcibly finish this broadcast
13494 forceReceive = true;
13495 r.state = BroadcastRecord.IDLE;
13496 }
13497 }
13498
13499 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013500 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013501 "processNextBroadcast() called when not idle (state="
13502 + r.state + ")");
13503 return;
13504 }
13505
13506 if (r.receivers == null || r.nextReceiver >= numReceivers
13507 || r.resultAbort || forceReceive) {
13508 // No more receivers for this broadcast! Send the final
13509 // result if requested...
13510 if (r.resultTo != null) {
13511 try {
13512 if (DEBUG_BROADCAST) {
13513 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013514 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013515 + " seq=" + seq + " app=" + r.callerApp);
13516 }
13517 performReceive(r.callerApp, r.resultTo,
13518 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013519 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013520 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013521 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013522 }
13523 }
13524
Joe Onorato8a9b2202010-02-26 18:56:32 -080013525 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013526 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13527
Joe Onorato8a9b2202010-02-26 18:56:32 -080013528 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013529 + r);
13530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013531 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013532 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013533 mOrderedBroadcasts.remove(0);
13534 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013535 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013536 continue;
13537 }
13538 } while (r == null);
13539
13540 // Get the next receiver...
13541 int recIdx = r.nextReceiver++;
13542
13543 // Keep track of when this receiver started, and make sure there
13544 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013545 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013546 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013547 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013548
Joe Onorato8a9b2202010-02-26 18:56:32 -080013549 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013550 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013551 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013552 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013553 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013554 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013555 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013556 }
13557
13558 Object nextReceiver = r.receivers.get(recIdx);
13559 if (nextReceiver instanceof BroadcastFilter) {
13560 // Simple case: this is a registered receiver who gets
13561 // a direct call.
13562 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013563 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013564 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013565 + filter + ": " + r);
13566 deliverToRegisteredReceiver(r, filter, r.ordered);
13567 if (r.receiver == null || !r.ordered) {
13568 // The receiver has already finished, so schedule to
13569 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013570 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13571 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013572 r.state = BroadcastRecord.IDLE;
13573 scheduleBroadcastsLocked();
13574 }
13575 return;
13576 }
13577
13578 // Hard case: need to instantiate the receiver, possibly
13579 // starting its application process to host it.
13580
13581 ResolveInfo info =
13582 (ResolveInfo)nextReceiver;
13583
13584 boolean skip = false;
13585 int perm = checkComponentPermission(info.activityInfo.permission,
13586 r.callingPid, r.callingUid,
13587 info.activityInfo.exported
13588 ? -1 : info.activityInfo.applicationInfo.uid);
13589 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013590 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013591 + r.intent.toString()
13592 + " from " + r.callerPackage + " (pid=" + r.callingPid
13593 + ", uid=" + r.callingUid + ")"
13594 + " requires " + info.activityInfo.permission
13595 + " due to receiver " + info.activityInfo.packageName
13596 + "/" + info.activityInfo.name);
13597 skip = true;
13598 }
13599 if (r.callingUid != Process.SYSTEM_UID &&
13600 r.requiredPermission != null) {
13601 try {
13602 perm = ActivityThread.getPackageManager().
13603 checkPermission(r.requiredPermission,
13604 info.activityInfo.applicationInfo.packageName);
13605 } catch (RemoteException e) {
13606 perm = PackageManager.PERMISSION_DENIED;
13607 }
13608 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013609 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013610 + r.intent + " to "
13611 + info.activityInfo.applicationInfo.packageName
13612 + " requires " + r.requiredPermission
13613 + " due to sender " + r.callerPackage
13614 + " (uid " + r.callingUid + ")");
13615 skip = true;
13616 }
13617 }
13618 if (r.curApp != null && r.curApp.crashing) {
13619 // If the target process is crashing, just skip it.
13620 skip = true;
13621 }
13622
13623 if (skip) {
13624 r.receiver = null;
13625 r.curFilter = null;
13626 r.state = BroadcastRecord.IDLE;
13627 scheduleBroadcastsLocked();
13628 return;
13629 }
13630
13631 r.state = BroadcastRecord.APP_RECEIVE;
13632 String targetProcess = info.activityInfo.processName;
13633 r.curComponent = new ComponentName(
13634 info.activityInfo.applicationInfo.packageName,
13635 info.activityInfo.name);
13636 r.curReceiver = info.activityInfo;
13637
13638 // Is this receiver's application already running?
13639 ProcessRecord app = getProcessRecordLocked(targetProcess,
13640 info.activityInfo.applicationInfo.uid);
13641 if (app != null && app.thread != null) {
13642 try {
13643 processCurBroadcastLocked(r, app);
13644 return;
13645 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013646 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013647 + r.curComponent, e);
13648 }
13649
13650 // If a dead object exception was thrown -- fall through to
13651 // restart the application.
13652 }
13653
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013654 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013655 if ((r.curApp=startProcessLocked(targetProcess,
13656 info.activityInfo.applicationInfo, true,
13657 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013658 "broadcast", r.curComponent,
13659 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13660 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013661 // Ah, this recipient is unavailable. Finish it if necessary,
13662 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013663 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013664 + info.activityInfo.applicationInfo.packageName + "/"
13665 + info.activityInfo.applicationInfo.uid + " for broadcast "
13666 + r.intent + ": process is bad");
13667 logBroadcastReceiverDiscard(r);
13668 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13669 r.resultExtras, r.resultAbort, true);
13670 scheduleBroadcastsLocked();
13671 r.state = BroadcastRecord.IDLE;
13672 return;
13673 }
13674
13675 mPendingBroadcast = r;
13676 }
13677 }
13678
13679 // =========================================================
13680 // INSTRUMENTATION
13681 // =========================================================
13682
13683 public boolean startInstrumentation(ComponentName className,
13684 String profileFile, int flags, Bundle arguments,
13685 IInstrumentationWatcher watcher) {
13686 // Refuse possible leaked file descriptors
13687 if (arguments != null && arguments.hasFileDescriptors()) {
13688 throw new IllegalArgumentException("File descriptors passed in Bundle");
13689 }
13690
13691 synchronized(this) {
13692 InstrumentationInfo ii = null;
13693 ApplicationInfo ai = null;
13694 try {
13695 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013696 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013697 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013698 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013699 } catch (PackageManager.NameNotFoundException e) {
13700 }
13701 if (ii == null) {
13702 reportStartInstrumentationFailure(watcher, className,
13703 "Unable to find instrumentation info for: " + className);
13704 return false;
13705 }
13706 if (ai == null) {
13707 reportStartInstrumentationFailure(watcher, className,
13708 "Unable to find instrumentation target package: " + ii.targetPackage);
13709 return false;
13710 }
13711
13712 int match = mContext.getPackageManager().checkSignatures(
13713 ii.targetPackage, ii.packageName);
13714 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13715 String msg = "Permission Denial: starting instrumentation "
13716 + className + " from pid="
13717 + Binder.getCallingPid()
13718 + ", uid=" + Binder.getCallingPid()
13719 + " not allowed because package " + ii.packageName
13720 + " does not have a signature matching the target "
13721 + ii.targetPackage;
13722 reportStartInstrumentationFailure(watcher, className, msg);
13723 throw new SecurityException(msg);
13724 }
13725
13726 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013727 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013728 ProcessRecord app = addAppLocked(ai);
13729 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013730 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013731 app.instrumentationProfileFile = profileFile;
13732 app.instrumentationArguments = arguments;
13733 app.instrumentationWatcher = watcher;
13734 app.instrumentationResultClass = className;
13735 Binder.restoreCallingIdentity(origId);
13736 }
13737
13738 return true;
13739 }
13740
13741 /**
13742 * Report errors that occur while attempting to start Instrumentation. Always writes the
13743 * error to the logs, but if somebody is watching, send the report there too. This enables
13744 * the "am" command to report errors with more information.
13745 *
13746 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13747 * @param cn The component name of the instrumentation.
13748 * @param report The error report.
13749 */
13750 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13751 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013752 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013753 try {
13754 if (watcher != null) {
13755 Bundle results = new Bundle();
13756 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13757 results.putString("Error", report);
13758 watcher.instrumentationStatus(cn, -1, results);
13759 }
13760 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013761 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013762 }
13763 }
13764
13765 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13766 if (app.instrumentationWatcher != null) {
13767 try {
13768 // NOTE: IInstrumentationWatcher *must* be oneway here
13769 app.instrumentationWatcher.instrumentationFinished(
13770 app.instrumentationClass,
13771 resultCode,
13772 results);
13773 } catch (RemoteException e) {
13774 }
13775 }
13776 app.instrumentationWatcher = null;
13777 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013778 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013779 app.instrumentationProfileFile = null;
13780 app.instrumentationArguments = null;
13781
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013782 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013783 }
13784
13785 public void finishInstrumentation(IApplicationThread target,
13786 int resultCode, Bundle results) {
13787 // Refuse possible leaked file descriptors
13788 if (results != null && results.hasFileDescriptors()) {
13789 throw new IllegalArgumentException("File descriptors passed in Intent");
13790 }
13791
13792 synchronized(this) {
13793 ProcessRecord app = getRecordForAppLocked(target);
13794 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013795 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013796 return;
13797 }
13798 final long origId = Binder.clearCallingIdentity();
13799 finishInstrumentationLocked(app, resultCode, results);
13800 Binder.restoreCallingIdentity(origId);
13801 }
13802 }
13803
13804 // =========================================================
13805 // CONFIGURATION
13806 // =========================================================
13807
13808 public ConfigurationInfo getDeviceConfigurationInfo() {
13809 ConfigurationInfo config = new ConfigurationInfo();
13810 synchronized (this) {
13811 config.reqTouchScreen = mConfiguration.touchscreen;
13812 config.reqKeyboardType = mConfiguration.keyboard;
13813 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013814 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13815 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013816 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13817 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013818 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13819 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013820 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13821 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013822 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013823 }
13824 return config;
13825 }
13826
13827 public Configuration getConfiguration() {
13828 Configuration ci;
13829 synchronized(this) {
13830 ci = new Configuration(mConfiguration);
13831 }
13832 return ci;
13833 }
13834
13835 public void updateConfiguration(Configuration values) {
13836 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13837 "updateConfiguration()");
13838
13839 synchronized(this) {
13840 if (values == null && mWindowManager != null) {
13841 // sentinel: fetch the current configuration from the window manager
13842 values = mWindowManager.computeNewConfiguration();
13843 }
13844
13845 final long origId = Binder.clearCallingIdentity();
13846 updateConfigurationLocked(values, null);
13847 Binder.restoreCallingIdentity(origId);
13848 }
13849 }
13850
13851 /**
13852 * Do either or both things: (1) change the current configuration, and (2)
13853 * make sure the given activity is running with the (now) current
13854 * configuration. Returns true if the activity has been left running, or
13855 * false if <var>starting</var> is being destroyed to match the new
13856 * configuration.
13857 */
13858 public boolean updateConfigurationLocked(Configuration values,
13859 HistoryRecord starting) {
13860 int changes = 0;
13861
13862 boolean kept = true;
13863
13864 if (values != null) {
13865 Configuration newConfig = new Configuration(mConfiguration);
13866 changes = newConfig.updateFrom(values);
13867 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013868 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013869 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013870 }
13871
Doug Zongker2bec3d42009-12-04 12:52:44 -080013872 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013873
13874 if (values.locale != null) {
13875 saveLocaleLocked(values.locale,
13876 !values.locale.equals(mConfiguration.locale),
13877 values.userSetLocale);
13878 }
13879
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013880 mConfigurationSeq++;
13881 if (mConfigurationSeq <= 0) {
13882 mConfigurationSeq = 1;
13883 }
13884 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013885 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013886 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013887
13888 AttributeCache ac = AttributeCache.instance();
13889 if (ac != null) {
13890 ac.updateConfiguration(mConfiguration);
13891 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013892
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013893 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13894 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13895 msg.obj = new Configuration(mConfiguration);
13896 mHandler.sendMessage(msg);
13897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013898
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013899 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13900 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013901 try {
13902 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013903 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013904 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013905 app.thread.scheduleConfigurationChanged(mConfiguration);
13906 }
13907 } catch (Exception e) {
13908 }
13909 }
13910 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013911 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13912 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013913 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13914 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013915 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13916 broadcastIntentLocked(null, null,
13917 new Intent(Intent.ACTION_LOCALE_CHANGED),
13918 null, null, 0, null, null,
13919 null, false, false, MY_PID, Process.SYSTEM_UID);
13920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013921 }
13922 }
13923
13924 if (changes != 0 && starting == null) {
13925 // If the configuration changed, and the caller is not already
13926 // in the process of starting an activity, then find the top
13927 // activity to check if its configuration needs to change.
13928 starting = topRunningActivityLocked(null);
13929 }
13930
13931 if (starting != null) {
13932 kept = ensureActivityConfigurationLocked(starting, changes);
13933 if (kept) {
13934 // If this didn't result in the starting activity being
13935 // destroyed, then we need to make sure at this point that all
13936 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013937 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013938 + ", ensuring others are correct.");
13939 ensureActivitiesVisibleLocked(starting, changes);
13940 }
13941 }
13942
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013943 if (values != null && mWindowManager != null) {
13944 mWindowManager.setNewConfiguration(mConfiguration);
13945 }
13946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013947 return kept;
13948 }
13949
13950 private final boolean relaunchActivityLocked(HistoryRecord r,
13951 int changes, boolean andResume) {
13952 List<ResultInfo> results = null;
13953 List<Intent> newIntents = null;
13954 if (andResume) {
13955 results = r.results;
13956 newIntents = r.newIntents;
13957 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013958 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013959 + " with results=" + results + " newIntents=" + newIntents
13960 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013961 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13962 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013963 r.task.taskId, r.shortComponentName);
13964
13965 r.startFreezingScreenLocked(r.app, 0);
13966
13967 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013968 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013969 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013970 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013971 // Note: don't need to call pauseIfSleepingLocked() here, because
13972 // the caller will only pass in 'andResume' if this activity is
13973 // currently resumed, which implies we aren't sleeping.
13974 } catch (RemoteException e) {
13975 return false;
13976 }
13977
13978 if (andResume) {
13979 r.results = null;
13980 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013981 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013982 }
13983
13984 return true;
13985 }
13986
13987 /**
13988 * Make sure the given activity matches the current configuration. Returns
13989 * false if the activity had to be destroyed. Returns true if the
13990 * configuration is the same, or the activity will remain running as-is
13991 * for whatever reason. Ensures the HistoryRecord is updated with the
13992 * correct configuration and all other bookkeeping is handled.
13993 */
13994 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13995 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070013996 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013997 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13998 "Skipping config check (will change): " + r);
13999 return true;
14000 }
14001
Joe Onorato8a9b2202010-02-26 18:56:32 -080014002 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014003 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014004
14005 // Short circuit: if the two configurations are the exact same
14006 // object (the common case), then there is nothing to do.
14007 Configuration newConfig = mConfiguration;
14008 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014009 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014010 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014011 return true;
14012 }
14013
14014 // We don't worry about activities that are finishing.
14015 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014016 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014017 "Configuration doesn't matter in finishing " + r);
14018 r.stopFreezingScreenLocked(false);
14019 return true;
14020 }
14021
14022 // Okay we now are going to make this activity have the new config.
14023 // But then we need to figure out how it needs to deal with that.
14024 Configuration oldConfig = r.configuration;
14025 r.configuration = newConfig;
14026
14027 // If the activity isn't currently running, just leave the new
14028 // configuration and it will pick that up next time it starts.
14029 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014030 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014031 "Configuration doesn't matter not running " + r);
14032 r.stopFreezingScreenLocked(false);
14033 return true;
14034 }
14035
14036 // If the activity isn't persistent, there is a chance we will
14037 // need to restart it.
14038 if (!r.persistent) {
14039
14040 // Figure out what has changed between the two configurations.
14041 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014042 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014043 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014044 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014045 + Integer.toHexString(r.info.configChanges)
14046 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014047 }
14048 if ((changes&(~r.info.configChanges)) != 0) {
14049 // Aha, the activity isn't handling the change, so DIE DIE DIE.
14050 r.configChangeFlags |= changes;
14051 r.startFreezingScreenLocked(r.app, globalChanges);
14052 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014053 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014054 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014055 destroyActivityLocked(r, true);
14056 } else if (r.state == ActivityState.PAUSING) {
14057 // A little annoying: we are waiting for this activity to
14058 // finish pausing. Let's not do anything now, but just
14059 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014060 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014061 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014062 r.configDestroy = true;
14063 return true;
14064 } else if (r.state == ActivityState.RESUMED) {
14065 // Try to optimize this case: the configuration is changing
14066 // and we need to restart the top, resumed activity.
14067 // Instead of doing the normal handshaking, just say
14068 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080014069 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014070 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014071 relaunchActivityLocked(r, r.configChangeFlags, true);
14072 r.configChangeFlags = 0;
14073 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014074 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014075 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014076 relaunchActivityLocked(r, r.configChangeFlags, false);
14077 r.configChangeFlags = 0;
14078 }
14079
14080 // All done... tell the caller we weren't able to keep this
14081 // activity around.
14082 return false;
14083 }
14084 }
14085
14086 // Default case: the activity can handle this new configuration, so
14087 // hand it over. Note that we don't need to give it the new
14088 // configuration, since we always send configuration changes to all
14089 // process when they happen so it can just use whatever configuration
14090 // it last got.
14091 if (r.app != null && r.app.thread != null) {
14092 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014093 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014094 r.app.thread.scheduleActivityConfigurationChanged(r);
14095 } catch (RemoteException e) {
14096 // If process died, whatever.
14097 }
14098 }
14099 r.stopFreezingScreenLocked(false);
14100
14101 return true;
14102 }
14103
14104 /**
14105 * Save the locale. You must be inside a synchronized (this) block.
14106 */
14107 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
14108 if(isDiff) {
14109 SystemProperties.set("user.language", l.getLanguage());
14110 SystemProperties.set("user.region", l.getCountry());
14111 }
14112
14113 if(isPersist) {
14114 SystemProperties.set("persist.sys.language", l.getLanguage());
14115 SystemProperties.set("persist.sys.country", l.getCountry());
14116 SystemProperties.set("persist.sys.localevar", l.getVariant());
14117 }
14118 }
14119
14120 // =========================================================
14121 // LIFETIME MANAGEMENT
14122 // =========================================================
14123
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014124 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
14125 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014126 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014127 // This adjustment has already been computed. If we are calling
14128 // from the top, we may have already computed our adjustment with
14129 // an earlier hidden adjustment that isn't really for us... if
14130 // so, use the new hidden adjustment.
14131 if (!recursed && app.hidden) {
14132 app.curAdj = hiddenAdj;
14133 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014134 return app.curAdj;
14135 }
14136
14137 if (app.thread == null) {
14138 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014139 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014140 return (app.curAdj=EMPTY_APP_ADJ);
14141 }
14142
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014143 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
14144 // The max adjustment doesn't allow this app to be anything
14145 // below foreground, so it is not worth doing work for it.
14146 app.adjType = "fixed";
14147 app.adjSeq = mAdjSeq;
14148 app.curRawAdj = app.maxAdj;
14149 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
14150 return (app.curAdj=app.maxAdj);
14151 }
14152
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014153 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014154 app.adjSource = null;
14155 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014156 app.empty = false;
14157 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014158
The Android Open Source Project4df24232009-03-05 14:34:35 -080014159 // Determine the importance of the process, starting with most
14160 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014161 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014162 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014163 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014164 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014165 // The last app on the list is the foreground app.
14166 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014167 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014168 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014169 } else if (app.instrumentationClass != null) {
14170 // Don't want to kill running instrumentation.
14171 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014172 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014173 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014174 } else if (app.persistentActivities > 0) {
14175 // Special persistent activities... shouldn't be used these days.
14176 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014177 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014178 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014179 } else if (app.curReceiver != null ||
14180 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
14181 // An app that is currently receiving a broadcast also
14182 // counts as being in the foreground.
14183 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014184 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014185 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014186 } else if (app.executingServices.size() > 0) {
14187 // An app that is currently executing a service callback also
14188 // counts as being in the foreground.
14189 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014190 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014191 app.adjType = "exec-service";
14192 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014193 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014194 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014195 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014196 app.adjType = "foreground-service";
14197 } else if (app.forcingToForeground != null) {
14198 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014199 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014200 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014201 app.adjType = "force-foreground";
14202 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014203 } else if (app == mHeavyWeightProcess) {
14204 // We don't want to kill the current heavy-weight process.
14205 adj = HEAVY_WEIGHT_APP_ADJ;
14206 schedGroup = Process.THREAD_GROUP_DEFAULT;
14207 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080014208 } else if (app == mHomeProcess) {
14209 // This process is hosting what we currently consider to be the
14210 // home app, so we don't want to let it go into the background.
14211 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014212 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014213 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014214 } else if ((N=app.activities.size()) != 0) {
14215 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014216 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014217 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014218 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014219 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014220 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014221 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014222 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014223 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014224 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014225 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014226 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014227 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014228 break;
14229 }
14230 }
14231 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014232 // A very not-needed process. If this is lower in the lru list,
14233 // we will push it in to the empty bucket.
14234 app.hidden = true;
14235 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014236 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014237 adj = hiddenAdj;
14238 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014239 }
14240
Joe Onorato8a9b2202010-02-26 18:56:32 -080014241 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014242
The Android Open Source Project4df24232009-03-05 14:34:35 -080014243 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014244 // there are applications dependent on our services or providers, but
14245 // this gives us a baseline and makes sure we don't get into an
14246 // infinite recursion.
14247 app.adjSeq = mAdjSeq;
14248 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014249
Christopher Tate6fa95972009-06-05 18:43:55 -070014250 if (mBackupTarget != null && app == mBackupTarget.app) {
14251 // If possible we want to avoid killing apps while they're being backed up
14252 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014253 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070014254 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014255 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014256 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070014257 }
14258 }
14259
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014260 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
14261 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014262 final long now = SystemClock.uptimeMillis();
14263 // This process is more important if the top activity is
14264 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070014265 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014266 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014267 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014268 if (s.startRequested) {
14269 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14270 // This service has seen some activity within
14271 // recent memory, so we will keep its process ahead
14272 // of the background processes.
14273 if (adj > SECONDARY_SERVER_ADJ) {
14274 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014275 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014276 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014277 }
14278 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014279 // If we have let the service slide into the background
14280 // state, still have some text describing what it is doing
14281 // even though the service no longer has an impact.
14282 if (adj > SECONDARY_SERVER_ADJ) {
14283 app.adjType = "started-bg-services";
14284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014285 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014286 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
14287 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014288 Iterator<ConnectionRecord> kt
14289 = s.connections.values().iterator();
14290 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14291 // XXX should compute this based on the max of
14292 // all connected clients.
14293 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014294 if (cr.binding.client == app) {
14295 // Binding to ourself is not interesting.
14296 continue;
14297 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014298 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
14299 ProcessRecord client = cr.binding.client;
14300 int myHiddenAdj = hiddenAdj;
14301 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014302 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014303 myHiddenAdj = client.hiddenAdj;
14304 } else {
14305 myHiddenAdj = VISIBLE_APP_ADJ;
14306 }
14307 }
14308 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014309 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014310 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014311 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014312 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014313 if (!client.hidden) {
14314 app.hidden = false;
14315 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014316 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014317 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14318 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014319 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014320 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014321 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014322 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14323 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14324 schedGroup = Process.THREAD_GROUP_DEFAULT;
14325 }
14326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014327 }
14328 HistoryRecord a = cr.activity;
14329 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014330 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014331 //}
14332 if (a != null && adj > FOREGROUND_APP_ADJ &&
14333 (a.state == ActivityState.RESUMED
14334 || a.state == ActivityState.PAUSING)) {
14335 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014336 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014337 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014338 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014339 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14340 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014341 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014342 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014343 }
14344 }
14345 }
14346 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014347
14348 // Finally, f this process has active services running in it, we
14349 // would like to avoid killing it unless it would prevent the current
14350 // application from running. By default we put the process in
14351 // with the rest of the background processes; as we scan through
14352 // its services we may bump it up from there.
14353 if (adj > hiddenAdj) {
14354 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014355 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014356 app.adjType = "bg-services";
14357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014358 }
14359
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014360 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
14361 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014362 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014363 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
14364 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014365 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014366 if (cpr.clients.size() != 0) {
14367 Iterator<ProcessRecord> kt = cpr.clients.iterator();
14368 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14369 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014370 if (client == app) {
14371 // Being our own client is not interesting.
14372 continue;
14373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014374 int myHiddenAdj = hiddenAdj;
14375 if (myHiddenAdj > client.hiddenAdj) {
14376 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
14377 myHiddenAdj = client.hiddenAdj;
14378 } else {
14379 myHiddenAdj = FOREGROUND_APP_ADJ;
14380 }
14381 }
14382 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014383 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014384 if (adj > clientAdj) {
14385 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014386 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014387 if (!client.hidden) {
14388 app.hidden = false;
14389 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014390 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014391 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14392 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014393 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014394 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014395 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014396 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14397 schedGroup = Process.THREAD_GROUP_DEFAULT;
14398 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014399 }
14400 }
14401 // If the provider has external (non-framework) process
14402 // dependencies, ensure that its adjustment is at least
14403 // FOREGROUND_APP_ADJ.
14404 if (cpr.externals != 0) {
14405 if (adj > FOREGROUND_APP_ADJ) {
14406 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014407 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014408 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014409 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014410 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014411 }
14412 }
14413 }
14414 }
14415
14416 app.curRawAdj = adj;
14417
Joe Onorato8a9b2202010-02-26 18:56:32 -080014418 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014419 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14420 if (adj > app.maxAdj) {
14421 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014422 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014423 schedGroup = Process.THREAD_GROUP_DEFAULT;
14424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014425 }
14426
14427 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014428 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014430 return adj;
14431 }
14432
14433 /**
14434 * Ask a given process to GC right now.
14435 */
14436 final void performAppGcLocked(ProcessRecord app) {
14437 try {
14438 app.lastRequestedGc = SystemClock.uptimeMillis();
14439 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014440 if (app.reportLowMemory) {
14441 app.reportLowMemory = false;
14442 app.thread.scheduleLowMemory();
14443 } else {
14444 app.thread.processInBackground();
14445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014446 }
14447 } catch (Exception e) {
14448 // whatever.
14449 }
14450 }
14451
14452 /**
14453 * Returns true if things are idle enough to perform GCs.
14454 */
Josh Bartel7f208742010-02-25 11:01:44 -060014455 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014456 return mParallelBroadcasts.size() == 0
14457 && mOrderedBroadcasts.size() == 0
14458 && (mSleeping || (mResumedActivity != null &&
14459 mResumedActivity.idle));
14460 }
14461
14462 /**
14463 * Perform GCs on all processes that are waiting for it, but only
14464 * if things are idle.
14465 */
14466 final void performAppGcsLocked() {
14467 final int N = mProcessesToGc.size();
14468 if (N <= 0) {
14469 return;
14470 }
Josh Bartel7f208742010-02-25 11:01:44 -060014471 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014472 while (mProcessesToGc.size() > 0) {
14473 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014474 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014475 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14476 <= SystemClock.uptimeMillis()) {
14477 // To avoid spamming the system, we will GC processes one
14478 // at a time, waiting a few seconds between each.
14479 performAppGcLocked(proc);
14480 scheduleAppGcsLocked();
14481 return;
14482 } else {
14483 // It hasn't been long enough since we last GCed this
14484 // process... put it in the list to wait for its time.
14485 addProcessToGcListLocked(proc);
14486 break;
14487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014488 }
14489 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014490
14491 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014492 }
14493 }
14494
14495 /**
14496 * If all looks good, perform GCs on all processes waiting for them.
14497 */
14498 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014499 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014500 performAppGcsLocked();
14501 return;
14502 }
14503 // Still not idle, wait some more.
14504 scheduleAppGcsLocked();
14505 }
14506
14507 /**
14508 * Schedule the execution of all pending app GCs.
14509 */
14510 final void scheduleAppGcsLocked() {
14511 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014512
14513 if (mProcessesToGc.size() > 0) {
14514 // Schedule a GC for the time to the next process.
14515 ProcessRecord proc = mProcessesToGc.get(0);
14516 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14517
14518 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14519 long now = SystemClock.uptimeMillis();
14520 if (when < (now+GC_TIMEOUT)) {
14521 when = now + GC_TIMEOUT;
14522 }
14523 mHandler.sendMessageAtTime(msg, when);
14524 }
14525 }
14526
14527 /**
14528 * Add a process to the array of processes waiting to be GCed. Keeps the
14529 * list in sorted order by the last GC time. The process can't already be
14530 * on the list.
14531 */
14532 final void addProcessToGcListLocked(ProcessRecord proc) {
14533 boolean added = false;
14534 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14535 if (mProcessesToGc.get(i).lastRequestedGc <
14536 proc.lastRequestedGc) {
14537 added = true;
14538 mProcessesToGc.add(i+1, proc);
14539 break;
14540 }
14541 }
14542 if (!added) {
14543 mProcessesToGc.add(0, proc);
14544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014545 }
14546
14547 /**
14548 * Set up to ask a process to GC itself. This will either do it
14549 * immediately, or put it on the list of processes to gc the next
14550 * time things are idle.
14551 */
14552 final void scheduleAppGcLocked(ProcessRecord app) {
14553 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014554 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014555 return;
14556 }
14557 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014558 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014559 scheduleAppGcsLocked();
14560 }
14561 }
14562
14563 private final boolean updateOomAdjLocked(
14564 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14565 app.hiddenAdj = hiddenAdj;
14566
14567 if (app.thread == null) {
14568 return true;
14569 }
14570
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014571 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014572
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014573 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014574 if (app.curRawAdj != app.setRawAdj) {
14575 if (app.curRawAdj > FOREGROUND_APP_ADJ
14576 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14577 // If this app is transitioning from foreground to
14578 // non-foreground, have it do a gc.
14579 scheduleAppGcLocked(app);
14580 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14581 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14582 // Likewise do a gc when an app is moving in to the
14583 // background (such as a service stopping).
14584 scheduleAppGcLocked(app);
14585 }
14586 app.setRawAdj = app.curRawAdj;
14587 }
14588 if (adj != app.setAdj) {
14589 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014590 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014591 TAG, "Set app " + app.processName +
14592 " oom adj to " + adj);
14593 app.setAdj = adj;
14594 } else {
14595 return false;
14596 }
14597 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014598 if (app.setSchedGroup != app.curSchedGroup) {
14599 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014600 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014601 "Setting process group of " + app.processName
14602 + " to " + app.curSchedGroup);
14603 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014604 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014605 try {
14606 Process.setProcessGroup(app.pid, app.curSchedGroup);
14607 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014608 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014609 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014610 e.printStackTrace();
14611 } finally {
14612 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014613 }
14614 }
14615 if (false) {
14616 if (app.thread != null) {
14617 try {
14618 app.thread.setSchedulingGroup(app.curSchedGroup);
14619 } catch (RemoteException e) {
14620 }
14621 }
14622 }
14623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014624 }
14625
14626 return true;
14627 }
14628
14629 private final HistoryRecord resumedAppLocked() {
14630 HistoryRecord resumedActivity = mResumedActivity;
14631 if (resumedActivity == null || resumedActivity.app == null) {
14632 resumedActivity = mPausingActivity;
14633 if (resumedActivity == null || resumedActivity.app == null) {
14634 resumedActivity = topRunningActivityLocked(null);
14635 }
14636 }
14637 return resumedActivity;
14638 }
14639
14640 private final boolean updateOomAdjLocked(ProcessRecord app) {
14641 final HistoryRecord TOP_ACT = resumedAppLocked();
14642 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14643 int curAdj = app.curAdj;
14644 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14645 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14646
14647 mAdjSeq++;
14648
14649 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14650 if (res) {
14651 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14652 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14653 if (nowHidden != wasHidden) {
14654 // Changed to/from hidden state, so apps after it in the LRU
14655 // list may also be changed.
14656 updateOomAdjLocked();
14657 }
14658 }
14659 return res;
14660 }
14661
14662 private final boolean updateOomAdjLocked() {
14663 boolean didOomAdj = true;
14664 final HistoryRecord TOP_ACT = resumedAppLocked();
14665 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14666
14667 if (false) {
14668 RuntimeException e = new RuntimeException();
14669 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014670 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014671 }
14672
14673 mAdjSeq++;
14674
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014675 // Let's determine how many processes we have running vs.
14676 // how many slots we have for background processes; we may want
14677 // to put multiple processes in a slot of there are enough of
14678 // them.
14679 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14680 int factor = (mLruProcesses.size()-4)/numSlots;
14681 if (factor < 1) factor = 1;
14682 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014683 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014685 // First try updating the OOM adjustment for each of the
14686 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014687 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014688 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14689 while (i > 0) {
14690 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014691 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014692 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014693 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014694 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014695 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014696 step++;
14697 if (step >= factor) {
14698 step = 0;
14699 curHiddenAdj++;
14700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014701 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014702 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070014703 if (!app.killedBackground) {
14704 numHidden++;
14705 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070014706 Slog.i(TAG, "No longer want " + app.processName
14707 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014708 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14709 app.processName, app.setAdj, "too many background");
14710 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070014711 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014712 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014713 }
14714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014715 } else {
14716 didOomAdj = false;
14717 }
14718 }
14719
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014720 // If we return false, we will fall back on killing processes to
14721 // have a fixed limit. Do this if a limit has been requested; else
14722 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014723 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14724 }
14725
14726 private final void trimApplications() {
14727 synchronized (this) {
14728 int i;
14729
14730 // First remove any unused application processes whose package
14731 // has been removed.
14732 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14733 final ProcessRecord app = mRemovedProcesses.get(i);
14734 if (app.activities.size() == 0
14735 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014736 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014737 TAG, "Exiting empty application process "
14738 + app.processName + " ("
14739 + (app.thread != null ? app.thread.asBinder() : null)
14740 + ")\n");
14741 if (app.pid > 0 && app.pid != MY_PID) {
14742 Process.killProcess(app.pid);
14743 } else {
14744 try {
14745 app.thread.scheduleExit();
14746 } catch (Exception e) {
14747 // Ignore exceptions.
14748 }
14749 }
14750 cleanUpApplicationRecordLocked(app, false, -1);
14751 mRemovedProcesses.remove(i);
14752
14753 if (app.persistent) {
14754 if (app.persistent) {
14755 addAppLocked(app.info);
14756 }
14757 }
14758 }
14759 }
14760
14761 // Now try updating the OOM adjustment for each of the
14762 // application processes based on their current state.
14763 // If the setOomAdj() API is not supported, then go with our
14764 // back-up plan...
14765 if (!updateOomAdjLocked()) {
14766
14767 // Count how many processes are running services.
14768 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014769 for (i=mLruProcesses.size()-1; i>=0; i--) {
14770 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014771
14772 if (app.persistent || app.services.size() != 0
14773 || app.curReceiver != null
14774 || app.persistentActivities > 0) {
14775 // Don't count processes holding services against our
14776 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014777 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014778 TAG, "Not trimming app " + app + " with services: "
14779 + app.services);
14780 numServiceProcs++;
14781 }
14782 }
14783
14784 int curMaxProcs = mProcessLimit;
14785 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14786 if (mAlwaysFinishActivities) {
14787 curMaxProcs = 1;
14788 }
14789 curMaxProcs += numServiceProcs;
14790
14791 // Quit as many processes as we can to get down to the desired
14792 // process count. First remove any processes that no longer
14793 // have activites running in them.
14794 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014795 i<mLruProcesses.size()
14796 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014797 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014798 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014799 // Quit an application only if it is not currently
14800 // running any activities.
14801 if (!app.persistent && app.activities.size() == 0
14802 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014803 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014804 TAG, "Exiting empty application process "
14805 + app.processName + " ("
14806 + (app.thread != null ? app.thread.asBinder() : null)
14807 + ")\n");
14808 if (app.pid > 0 && app.pid != MY_PID) {
14809 Process.killProcess(app.pid);
14810 } else {
14811 try {
14812 app.thread.scheduleExit();
14813 } catch (Exception e) {
14814 // Ignore exceptions.
14815 }
14816 }
14817 // todo: For now we assume the application is not buggy
14818 // or evil, and will quit as a result of our request.
14819 // Eventually we need to drive this off of the death
14820 // notification, and kill the process if it takes too long.
14821 cleanUpApplicationRecordLocked(app, false, i);
14822 i--;
14823 }
14824 }
14825
14826 // If we still have too many processes, now from the least
14827 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014828 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014829 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014830 " of " + curMaxProcs + " processes");
14831 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014832 i<mLruProcesses.size()
14833 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014834 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014835 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014836 // Quit the application only if we have a state saved for
14837 // all of its activities.
14838 boolean canQuit = !app.persistent && app.curReceiver == null
14839 && app.services.size() == 0
14840 && app.persistentActivities == 0;
14841 int NUMA = app.activities.size();
14842 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014843 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014844 TAG, "Looking to quit " + app.processName);
14845 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014846 HistoryRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014847 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014848 TAG, " " + r.intent.getComponent().flattenToShortString()
14849 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14850 canQuit = (r.haveState || !r.stateNotNeeded)
14851 && !r.visible && r.stopped;
14852 }
14853 if (canQuit) {
14854 // Finish all of the activities, and then the app itself.
14855 for (j=0; j<NUMA; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014856 HistoryRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014857 if (!r.finishing) {
14858 destroyActivityLocked(r, false);
14859 }
14860 r.resultTo = null;
14861 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014862 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014863 + app.processName + " ("
14864 + (app.thread != null ? app.thread.asBinder() : null)
14865 + ")\n");
14866 if (app.pid > 0 && app.pid != MY_PID) {
14867 Process.killProcess(app.pid);
14868 } else {
14869 try {
14870 app.thread.scheduleExit();
14871 } catch (Exception e) {
14872 // Ignore exceptions.
14873 }
14874 }
14875 // todo: For now we assume the application is not buggy
14876 // or evil, and will quit as a result of our request.
14877 // Eventually we need to drive this off of the death
14878 // notification, and kill the process if it takes too long.
14879 cleanUpApplicationRecordLocked(app, false, i);
14880 i--;
14881 //dump();
14882 }
14883 }
14884
14885 }
14886
14887 int curMaxActivities = MAX_ACTIVITIES;
14888 if (mAlwaysFinishActivities) {
14889 curMaxActivities = 1;
14890 }
14891
14892 // Finally, if there are too many activities now running, try to
14893 // finish as many as we can to get back down to the limit.
14894 for ( i=0;
14895 i<mLRUActivities.size()
14896 && mLRUActivities.size() > curMaxActivities;
14897 i++) {
14898 final HistoryRecord r
14899 = (HistoryRecord)mLRUActivities.get(i);
14900
14901 // We can finish this one if we have its icicle saved and
14902 // it is not persistent.
14903 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14904 && r.stopped && !r.persistent && !r.finishing) {
14905 final int origSize = mLRUActivities.size();
14906 destroyActivityLocked(r, true);
14907
14908 // This will remove it from the LRU list, so keep
14909 // our index at the same value. Note that this check to
14910 // see if the size changes is just paranoia -- if
14911 // something unexpected happens, we don't want to end up
14912 // in an infinite loop.
14913 if (origSize > mLRUActivities.size()) {
14914 i--;
14915 }
14916 }
14917 }
14918 }
14919 }
14920
14921 /** This method sends the specified signal to each of the persistent apps */
14922 public void signalPersistentProcesses(int sig) throws RemoteException {
14923 if (sig != Process.SIGNAL_USR1) {
14924 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14925 }
14926
14927 synchronized (this) {
14928 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14929 != PackageManager.PERMISSION_GRANTED) {
14930 throw new SecurityException("Requires permission "
14931 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14932 }
14933
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014934 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14935 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014936 if (r.thread != null && r.persistent) {
14937 Process.sendSignal(r.pid, sig);
14938 }
14939 }
14940 }
14941 }
14942
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014943 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014944 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014945
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014946 try {
14947 synchronized (this) {
14948 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14949 // its own permission.
14950 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14951 != PackageManager.PERMISSION_GRANTED) {
14952 throw new SecurityException("Requires permission "
14953 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014954 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014955
14956 if (start && fd == null) {
14957 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014958 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014959
14960 ProcessRecord proc = null;
14961 try {
14962 int pid = Integer.parseInt(process);
14963 synchronized (mPidsSelfLocked) {
14964 proc = mPidsSelfLocked.get(pid);
14965 }
14966 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014967 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014968
14969 if (proc == null) {
14970 HashMap<String, SparseArray<ProcessRecord>> all
14971 = mProcessNames.getMap();
14972 SparseArray<ProcessRecord> procs = all.get(process);
14973 if (procs != null && procs.size() > 0) {
14974 proc = procs.valueAt(0);
14975 }
14976 }
14977
14978 if (proc == null || proc.thread == null) {
14979 throw new IllegalArgumentException("Unknown process: " + process);
14980 }
14981
14982 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14983 if (isSecure) {
14984 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14985 throw new SecurityException("Process not debuggable: " + proc);
14986 }
14987 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014988
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014989 proc.thread.profilerControl(start, path, fd);
14990 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014991 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014992 }
14993 } catch (RemoteException e) {
14994 throw new IllegalStateException("Process disappeared");
14995 } finally {
14996 if (fd != null) {
14997 try {
14998 fd.close();
14999 } catch (IOException e) {
15000 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015001 }
15002 }
15003 }
15004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015005 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
15006 public void monitor() {
15007 synchronized (this) { }
15008 }
15009}