blob: d59ecdd4a5bc8e977685ed2cabc2776e9a4ca8a7 [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
Daniel Sandler69a48172010-06-23 16:29:36 -04008728 public void setImmersive(IBinder token, boolean immersive) {
8729 synchronized(this) {
8730 int index = (token != null) ? indexOfTokenLocked(token) : -1;
8731 if (index < 0) {
8732 throw new IllegalArgumentException();
8733 }
8734 HistoryRecord r = (HistoryRecord)mHistory.get(index);
8735 r.immersive = immersive;
8736 }
8737 }
8738
8739 public boolean isImmersive(IBinder token) {
8740 synchronized (this) {
8741 int index = (token != null) ? indexOfTokenLocked(token) : -1;
8742 if (index < 0) {
8743 throw new IllegalArgumentException();
8744 }
8745 HistoryRecord r = (HistoryRecord)mHistory.get(index);
8746 return r.immersive;
8747 }
8748 }
8749
8750 public boolean isTopActivityImmersive() {
8751 synchronized (this) {
8752 HistoryRecord r = topRunningActivityLocked(null);
8753 return (r != null) ? r.immersive : false;
8754 }
8755 }
8756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008757 public final void enterSafeMode() {
8758 synchronized(this) {
8759 // It only makes sense to do this before the system is ready
8760 // and started launching other packages.
8761 if (!mSystemReady) {
8762 try {
8763 ActivityThread.getPackageManager().enterSafeMode();
8764 } catch (RemoteException e) {
8765 }
8766
8767 View v = LayoutInflater.from(mContext).inflate(
8768 com.android.internal.R.layout.safe_mode, null);
8769 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8770 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8771 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8772 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8773 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8774 lp.format = v.getBackground().getOpacity();
8775 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8776 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8777 ((WindowManager)mContext.getSystemService(
8778 Context.WINDOW_SERVICE)).addView(v, lp);
8779 }
8780 }
8781 }
8782
8783 public void noteWakeupAlarm(IIntentSender sender) {
8784 if (!(sender instanceof PendingIntentRecord)) {
8785 return;
8786 }
8787 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8788 synchronized (stats) {
8789 if (mBatteryStatsService.isOnBattery()) {
8790 mBatteryStatsService.enforceCallingPermission();
8791 PendingIntentRecord rec = (PendingIntentRecord)sender;
8792 int MY_UID = Binder.getCallingUid();
8793 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8794 BatteryStatsImpl.Uid.Pkg pkg =
8795 stats.getPackageStatsLocked(uid, rec.key.packageName);
8796 pkg.incWakeupsLocked();
8797 }
8798 }
8799 }
8800
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008801 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008802 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008803 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008804 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008805 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008806 // XXX Note: don't acquire main activity lock here, because the window
8807 // manager calls in with its locks held.
8808
8809 boolean killed = false;
8810 synchronized (mPidsSelfLocked) {
8811 int[] types = new int[pids.length];
8812 int worstType = 0;
8813 for (int i=0; i<pids.length; i++) {
8814 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8815 if (proc != null) {
8816 int type = proc.setAdj;
8817 types[i] = type;
8818 if (type > worstType) {
8819 worstType = type;
8820 }
8821 }
8822 }
8823
8824 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8825 // then constrain it so we will kill all hidden procs.
8826 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8827 worstType = HIDDEN_APP_MIN_ADJ;
8828 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008829 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008830 for (int i=0; i<pids.length; i++) {
8831 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8832 if (proc == null) {
8833 continue;
8834 }
8835 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008836 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008837 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008838 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8839 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008840 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008841 proc.killedBackground = true;
8842 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008843 }
8844 }
8845 }
8846 return killed;
8847 }
8848
8849 public void reportPss(IApplicationThread caller, int pss) {
8850 Watchdog.PssRequestor req;
8851 String name;
8852 ProcessRecord callerApp;
8853 synchronized (this) {
8854 if (caller == null) {
8855 return;
8856 }
8857 callerApp = getRecordForAppLocked(caller);
8858 if (callerApp == null) {
8859 return;
8860 }
8861 callerApp.lastPss = pss;
8862 req = callerApp;
8863 name = callerApp.processName;
8864 }
8865 Watchdog.getInstance().reportPss(req, name, pss);
8866 if (!callerApp.persistent) {
8867 removeRequestedPss(callerApp);
8868 }
8869 }
8870
8871 public void requestPss(Runnable completeCallback) {
8872 ArrayList<ProcessRecord> procs;
8873 synchronized (this) {
8874 mRequestPssCallback = completeCallback;
8875 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008876 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8877 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008878 if (!proc.persistent) {
8879 mRequestPssList.add(proc);
8880 }
8881 }
8882 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8883 }
8884
8885 int oldPri = Process.getThreadPriority(Process.myTid());
8886 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8887 for (int i=procs.size()-1; i>=0; i--) {
8888 ProcessRecord proc = procs.get(i);
8889 proc.lastPss = 0;
8890 proc.requestPss();
8891 }
8892 Process.setThreadPriority(oldPri);
8893 }
8894
8895 void removeRequestedPss(ProcessRecord proc) {
8896 Runnable callback = null;
8897 synchronized (this) {
8898 if (mRequestPssList.remove(proc)) {
8899 if (mRequestPssList.size() == 0) {
8900 callback = mRequestPssCallback;
8901 mRequestPssCallback = null;
8902 }
8903 }
8904 }
8905
8906 if (callback != null) {
8907 callback.run();
8908 }
8909 }
8910
8911 public void collectPss(Watchdog.PssStats stats) {
8912 stats.mEmptyPss = 0;
8913 stats.mEmptyCount = 0;
8914 stats.mBackgroundPss = 0;
8915 stats.mBackgroundCount = 0;
8916 stats.mServicePss = 0;
8917 stats.mServiceCount = 0;
8918 stats.mVisiblePss = 0;
8919 stats.mVisibleCount = 0;
8920 stats.mForegroundPss = 0;
8921 stats.mForegroundCount = 0;
8922 stats.mNoPssCount = 0;
8923 synchronized (this) {
8924 int i;
8925 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8926 ? mProcDeaths.length : stats.mProcDeaths.length;
8927 int aggr = 0;
8928 for (i=0; i<NPD; i++) {
8929 aggr += mProcDeaths[i];
8930 stats.mProcDeaths[i] = aggr;
8931 }
8932 while (i<stats.mProcDeaths.length) {
8933 stats.mProcDeaths[i] = 0;
8934 i++;
8935 }
8936
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008937 for (i=mLruProcesses.size()-1; i>=0; i--) {
8938 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008939 if (proc.persistent) {
8940 continue;
8941 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008942 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008943 if (proc.lastPss == 0) {
8944 stats.mNoPssCount++;
8945 continue;
8946 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008947 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8948 if (proc.empty) {
8949 stats.mEmptyPss += proc.lastPss;
8950 stats.mEmptyCount++;
8951 } else {
8952 stats.mBackgroundPss += proc.lastPss;
8953 stats.mBackgroundCount++;
8954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008955 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8956 stats.mVisiblePss += proc.lastPss;
8957 stats.mVisibleCount++;
8958 } else {
8959 stats.mForegroundPss += proc.lastPss;
8960 stats.mForegroundCount++;
8961 }
8962 }
8963 }
8964 }
8965
8966 public final void startRunning(String pkg, String cls, String action,
8967 String data) {
8968 synchronized(this) {
8969 if (mStartRunning) {
8970 return;
8971 }
8972 mStartRunning = true;
8973 mTopComponent = pkg != null && cls != null
8974 ? new ComponentName(pkg, cls) : null;
8975 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8976 mTopData = data;
8977 if (!mSystemReady) {
8978 return;
8979 }
8980 }
8981
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008982 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008983 }
8984
8985 private void retrieveSettings() {
8986 final ContentResolver resolver = mContext.getContentResolver();
8987 String debugApp = Settings.System.getString(
8988 resolver, Settings.System.DEBUG_APP);
8989 boolean waitForDebugger = Settings.System.getInt(
8990 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8991 boolean alwaysFinishActivities = Settings.System.getInt(
8992 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8993
8994 Configuration configuration = new Configuration();
8995 Settings.System.getConfiguration(resolver, configuration);
8996
8997 synchronized (this) {
8998 mDebugApp = mOrigDebugApp = debugApp;
8999 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
9000 mAlwaysFinishActivities = alwaysFinishActivities;
9001 // This happens before any activities are started, so we can
9002 // change mConfiguration in-place.
9003 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009004 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009005 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009006 }
9007 }
9008
9009 public boolean testIsSystemReady() {
9010 // no need to synchronize(this) just to read & return the value
9011 return mSystemReady;
9012 }
9013
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009014 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009015 // In the simulator, startRunning will never have been called, which
9016 // normally sets a few crucial variables. Do it here instead.
9017 if (!Process.supportsProcesses()) {
9018 mStartRunning = true;
9019 mTopAction = Intent.ACTION_MAIN;
9020 }
9021
9022 synchronized(this) {
9023 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009024 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009025 return;
9026 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009027
9028 // Check to see if there are any update receivers to run.
9029 if (!mDidUpdate) {
9030 if (mWaitingUpdate) {
9031 return;
9032 }
9033 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
9034 List<ResolveInfo> ris = null;
9035 try {
9036 ris = ActivityThread.getPackageManager().queryIntentReceivers(
9037 intent, null, 0);
9038 } catch (RemoteException e) {
9039 }
9040 if (ris != null) {
9041 for (int i=ris.size()-1; i>=0; i--) {
9042 if ((ris.get(i).activityInfo.applicationInfo.flags
9043 &ApplicationInfo.FLAG_SYSTEM) == 0) {
9044 ris.remove(i);
9045 }
9046 }
9047 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
9048 for (int i=0; i<ris.size(); i++) {
9049 ActivityInfo ai = ris.get(i).activityInfo;
9050 intent.setComponent(new ComponentName(ai.packageName, ai.name));
9051 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08009052 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009053 finisher = new IIntentReceiver.Stub() {
9054 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07009055 String data, Bundle extras, boolean ordered,
9056 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009057 throws RemoteException {
9058 synchronized (ActivityManagerService.this) {
9059 mDidUpdate = true;
9060 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009061 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009062 }
9063 };
9064 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009065 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009066 broadcastIntentLocked(null, null, intent, null, finisher,
9067 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08009068 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009069 mWaitingUpdate = true;
9070 }
9071 }
9072 }
9073 if (mWaitingUpdate) {
9074 return;
9075 }
9076 mDidUpdate = true;
9077 }
9078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009079 mSystemReady = true;
9080 if (!mStartRunning) {
9081 return;
9082 }
9083 }
9084
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009085 ArrayList<ProcessRecord> procsToKill = null;
9086 synchronized(mPidsSelfLocked) {
9087 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
9088 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
9089 if (!isAllowedWhileBooting(proc.info)){
9090 if (procsToKill == null) {
9091 procsToKill = new ArrayList<ProcessRecord>();
9092 }
9093 procsToKill.add(proc);
9094 }
9095 }
9096 }
9097
9098 if (procsToKill != null) {
9099 synchronized(this) {
9100 for (int i=procsToKill.size()-1; i>=0; i--) {
9101 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009102 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009103 removeProcessLocked(proc, true);
9104 }
9105 }
9106 }
9107
Joe Onorato8a9b2202010-02-26 18:56:32 -08009108 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009109 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009110 SystemClock.uptimeMillis());
9111
9112 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009113 // Make sure we have no pre-ready processes sitting around.
9114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009115 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
9116 ResolveInfo ri = mContext.getPackageManager()
9117 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07009118 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009119 CharSequence errorMsg = null;
9120 if (ri != null) {
9121 ActivityInfo ai = ri.activityInfo;
9122 ApplicationInfo app = ai.applicationInfo;
9123 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
9124 mTopAction = Intent.ACTION_FACTORY_TEST;
9125 mTopData = null;
9126 mTopComponent = new ComponentName(app.packageName,
9127 ai.name);
9128 } else {
9129 errorMsg = mContext.getResources().getText(
9130 com.android.internal.R.string.factorytest_not_system);
9131 }
9132 } else {
9133 errorMsg = mContext.getResources().getText(
9134 com.android.internal.R.string.factorytest_no_action);
9135 }
9136 if (errorMsg != null) {
9137 mTopAction = null;
9138 mTopData = null;
9139 mTopComponent = null;
9140 Message msg = Message.obtain();
9141 msg.what = SHOW_FACTORY_ERROR_MSG;
9142 msg.getData().putCharSequence("msg", errorMsg);
9143 mHandler.sendMessage(msg);
9144 }
9145 }
9146 }
9147
9148 retrieveSettings();
9149
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009150 if (goingCallback != null) goingCallback.run();
9151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009152 synchronized (this) {
9153 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
9154 try {
9155 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009156 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009157 if (apps != null) {
9158 int N = apps.size();
9159 int i;
9160 for (i=0; i<N; i++) {
9161 ApplicationInfo info
9162 = (ApplicationInfo)apps.get(i);
9163 if (info != null &&
9164 !info.packageName.equals("android")) {
9165 addAppLocked(info);
9166 }
9167 }
9168 }
9169 } catch (RemoteException ex) {
9170 // pm is in same process, this will never happen.
9171 }
9172 }
9173
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009174 // Start up initial activity.
9175 mBooting = true;
9176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 try {
9178 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
9179 Message msg = Message.obtain();
9180 msg.what = SHOW_UID_ERROR_MSG;
9181 mHandler.sendMessage(msg);
9182 }
9183 } catch (RemoteException e) {
9184 }
9185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009186 resumeTopActivityLocked(null);
9187 }
9188 }
9189
Dan Egnorb7f03672009-12-09 16:22:32 -08009190 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009191 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009192 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009193 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009194 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009195 startAppProblemLocked(app);
9196 app.stopFreezingAllLocked();
9197 return handleAppCrashLocked(app);
9198 }
9199
Dan Egnorb7f03672009-12-09 16:22:32 -08009200 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009201 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009202 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009203 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009204 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
9205 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009206 startAppProblemLocked(app);
9207 app.stopFreezingAllLocked();
9208 }
9209
9210 /**
9211 * Generate a process error record, suitable for attachment to a ProcessRecord.
9212 *
9213 * @param app The ProcessRecord in which the error occurred.
9214 * @param condition Crashing, Application Not Responding, etc. Values are defined in
9215 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08009216 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009217 * @param shortMsg Short message describing the crash.
9218 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08009219 * @param stackTrace Full crash stack trace, may be null.
9220 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 * @return Returns a fully-formed AppErrorStateInfo record.
9222 */
9223 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009224 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009225 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08009226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009227 report.condition = condition;
9228 report.processName = app.processName;
9229 report.pid = app.pid;
9230 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08009231 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009232 report.shortMsg = shortMsg;
9233 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08009234 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009235
9236 return report;
9237 }
9238
Dan Egnor42471dd2010-01-07 17:25:22 -08009239 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 synchronized (this) {
9241 app.crashing = false;
9242 app.crashingReport = null;
9243 app.notResponding = false;
9244 app.notRespondingReport = null;
9245 if (app.anrDialog == fromDialog) {
9246 app.anrDialog = null;
9247 }
9248 if (app.waitDialog == fromDialog) {
9249 app.waitDialog = null;
9250 }
9251 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009252 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07009253 Slog.i(ActivityManagerService.TAG, "Killing "
9254 + app.processName + " (pid=" + app.pid + "): user's request");
9255 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
9256 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009257 Process.killProcess(app.pid);
9258 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009259 }
9260 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009261
Dan Egnorb7f03672009-12-09 16:22:32 -08009262 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009263 long now = SystemClock.uptimeMillis();
9264
9265 Long crashTime = mProcessCrashTimes.get(app.info.processName,
9266 app.info.uid);
9267 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
9268 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08009269 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009270 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009271 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009272 app.info.processName, app.info.uid);
9273 killServicesLocked(app, false);
9274 for (int i=mHistory.size()-1; i>=0; i--) {
9275 HistoryRecord r = (HistoryRecord)mHistory.get(i);
9276 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009277 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009278 + r.intent.getComponent().flattenToShortString());
9279 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
9280 }
9281 }
9282 if (!app.persistent) {
9283 // We don't want to start this process again until the user
9284 // explicitly does so... but for persistent process, we really
9285 // need to keep it running. If a persistent process is actually
9286 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08009287 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009288 app.info.processName);
9289 mBadProcesses.put(app.info.processName, app.info.uid, now);
9290 app.bad = true;
9291 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
9292 app.removed = true;
9293 removeProcessLocked(app, false);
9294 return false;
9295 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009296 } else {
9297 HistoryRecord r = topRunningActivityLocked(null);
9298 if (r.app == app) {
9299 // If the top running activity is from this crashing
9300 // process, then terminate it to avoid getting in a loop.
9301 Slog.w(TAG, " Force finishing activity "
9302 + r.intent.getComponent().flattenToShortString());
9303 int index = indexOfTokenLocked(r);
9304 finishActivityLocked(r, index,
9305 Activity.RESULT_CANCELED, null, "crashed");
9306 // Also terminate an activities below it that aren't yet
9307 // stopped, to avoid a situation where one will get
9308 // re-start our crashing activity once it gets resumed again.
9309 index--;
9310 if (index >= 0) {
9311 r = (HistoryRecord)mHistory.get(index);
9312 if (r.state == ActivityState.RESUMED
9313 || r.state == ActivityState.PAUSING
9314 || r.state == ActivityState.PAUSED) {
9315 if (!r.isHomeActivity) {
9316 Slog.w(TAG, " Force finishing activity "
9317 + r.intent.getComponent().flattenToShortString());
9318 finishActivityLocked(r, index,
9319 Activity.RESULT_CANCELED, null, "crashed");
9320 }
9321 }
9322 }
9323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009324 }
9325
9326 // Bump up the crash count of any services currently running in the proc.
9327 if (app.services.size() != 0) {
9328 // Any services running in the application need to be placed
9329 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009330 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009331 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009332 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009333 sr.crashCount++;
9334 }
9335 }
9336
9337 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
9338 return true;
9339 }
9340
9341 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009342 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9343 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009344 skipCurrentReceiverLocked(app);
9345 }
9346
9347 void skipCurrentReceiverLocked(ProcessRecord app) {
9348 boolean reschedule = false;
9349 BroadcastRecord r = app.curReceiver;
9350 if (r != null) {
9351 // The current broadcast is waiting for this app's receiver
9352 // to be finished. Looks like that's not going to happen, so
9353 // let the broadcast continue.
9354 logBroadcastReceiverDiscard(r);
9355 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9356 r.resultExtras, r.resultAbort, true);
9357 reschedule = true;
9358 }
9359 r = mPendingBroadcast;
9360 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009361 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009362 "skip & discard pending app " + r);
9363 logBroadcastReceiverDiscard(r);
9364 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9365 r.resultExtras, r.resultAbort, true);
9366 reschedule = true;
9367 }
9368 if (reschedule) {
9369 scheduleBroadcastsLocked();
9370 }
9371 }
9372
Dan Egnor60d87622009-12-16 16:32:58 -08009373 /**
9374 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9375 * The application process will exit immediately after this call returns.
9376 * @param app object of the crashing app, null for the system server
9377 * @param crashInfo describing the exception
9378 */
9379 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9380 ProcessRecord r = findAppProcess(app);
9381
9382 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9383 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009384 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009385 crashInfo.exceptionClassName,
9386 crashInfo.exceptionMessage,
9387 crashInfo.throwFileName,
9388 crashInfo.throwLineNumber);
9389
Dan Egnor42471dd2010-01-07 17:25:22 -08009390 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009391
9392 crashApplication(r, crashInfo);
9393 }
9394
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009395 public void handleApplicationStrictModeViolation(
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009396 IBinder app, int violationMask, ApplicationErrorReport.CrashInfo crashInfo) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009397 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009398
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009399 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009400 Integer stackFingerprint = crashInfo.stackTrace.hashCode();
9401 boolean logIt = true;
9402 synchronized (mAlreadyLoggedViolatedStacks) {
9403 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
9404 logIt = false;
9405 // TODO: sub-sample into EventLog for these, with
9406 // the crashInfo.durationMillis? Then we'd get
9407 // the relative pain numbers, without logging all
9408 // the stack traces repeatedly. We'd want to do
9409 // likewise in the client code, which also does
9410 // dup suppression, before the Binder call.
9411 } else {
9412 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
9413 mAlreadyLoggedViolatedStacks.clear();
9414 }
9415 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
9416 }
9417 }
9418 if (logIt) {
9419 addErrorToDropBox("strictmode", r, null, null, null, null, null, crashInfo);
9420 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009421 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009422
9423 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
9424 AppErrorResult result = new AppErrorResult();
9425 synchronized (this) {
9426 final long origId = Binder.clearCallingIdentity();
9427
9428 Message msg = Message.obtain();
9429 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
9430 HashMap<String, Object> data = new HashMap<String, Object>();
9431 data.put("result", result);
9432 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009433 data.put("violationMask", violationMask);
9434 data.put("crashInfo", crashInfo);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009435 msg.obj = data;
9436 mHandler.sendMessage(msg);
9437
9438 Binder.restoreCallingIdentity(origId);
9439 }
9440 int res = result.get();
9441 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
9442 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009443 }
9444
Dan Egnor60d87622009-12-16 16:32:58 -08009445 /**
9446 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9447 * @param app object of the crashing app, null for the system server
9448 * @param tag reported by the caller
9449 * @param crashInfo describing the context of the error
9450 * @return true if the process should exit immediately (WTF is fatal)
9451 */
9452 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009453 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009454 ProcessRecord r = findAppProcess(app);
9455
9456 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9457 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009458 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009459 tag, crashInfo.exceptionMessage);
9460
Dan Egnor42471dd2010-01-07 17:25:22 -08009461 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009462
Doug Zongker43866e02010-01-07 12:09:54 -08009463 if (Settings.Secure.getInt(mContext.getContentResolver(),
9464 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009465 crashApplication(r, crashInfo);
9466 return true;
9467 } else {
9468 return false;
9469 }
9470 }
9471
9472 /**
9473 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9474 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9475 */
9476 private ProcessRecord findAppProcess(IBinder app) {
9477 if (app == null) {
9478 return null;
9479 }
9480
9481 synchronized (this) {
9482 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9483 final int NA = apps.size();
9484 for (int ia=0; ia<NA; ia++) {
9485 ProcessRecord p = apps.valueAt(ia);
9486 if (p.thread != null && p.thread.asBinder() == app) {
9487 return p;
9488 }
9489 }
9490 }
9491
Joe Onorato8a9b2202010-02-26 18:56:32 -08009492 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009493 return null;
9494 }
9495 }
9496
9497 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009498 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009499 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009500 * @param process which caused the error, null means the system server
9501 * @param activity which triggered the error, null if unknown
9502 * @param parent activity related to the error, null if unknown
9503 * @param subject line related to the error, null if absent
9504 * @param report in long form describing the error, null if absent
9505 * @param logFile to include in the report, null if none
9506 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009507 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009508 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009509 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9510 final String report, final File logFile,
9511 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009512 // NOTE -- this must never acquire the ActivityManagerService lock,
9513 // otherwise the watchdog may be prevented from resetting the system.
9514
Dan Egnora455d192010-03-12 08:52:28 -08009515 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009516 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009517 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009518 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009519 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009520 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009521 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009522 }
9523
Dan Egnora455d192010-03-12 08:52:28 -08009524 final String dropboxTag = prefix + eventType;
9525 final DropBoxManager dbox = (DropBoxManager)
9526 mContext.getSystemService(Context.DROPBOX_SERVICE);
9527
9528 // Exit early if the dropbox isn't configured to accept this report type.
9529 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9530
9531 final StringBuilder sb = new StringBuilder(1024);
9532 if (process == null || process.pid == MY_PID) {
9533 sb.append("Process: system_server\n");
9534 } else {
9535 sb.append("Process: ").append(process.processName).append("\n");
9536 }
9537 if (process != null) {
9538 int flags = process.info.flags;
9539 IPackageManager pm = ActivityThread.getPackageManager();
9540 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9541 for (String pkg : process.pkgList) {
9542 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009543 try {
Dan Egnora455d192010-03-12 08:52:28 -08009544 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9545 if (pi != null) {
9546 sb.append(" v").append(pi.versionCode);
9547 if (pi.versionName != null) {
9548 sb.append(" (").append(pi.versionName).append(")");
9549 }
9550 }
9551 } catch (RemoteException e) {
9552 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009553 }
Dan Egnora455d192010-03-12 08:52:28 -08009554 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009555 }
Dan Egnora455d192010-03-12 08:52:28 -08009556 }
9557 if (activity != null) {
9558 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9559 }
9560 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9561 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9562 }
9563 if (parent != null && parent != activity) {
9564 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9565 }
9566 if (subject != null) {
9567 sb.append("Subject: ").append(subject).append("\n");
9568 }
9569 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Brad Fitzpatrick04b243d2010-06-21 08:01:13 -07009570 if (crashInfo != null && crashInfo.durationMillis != -1) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009571 sb.append("Duration-Millis: ").append(crashInfo.durationMillis).append("\n");
9572 }
Dan Egnora455d192010-03-12 08:52:28 -08009573 sb.append("\n");
9574
9575 // Do the rest in a worker thread to avoid blocking the caller on I/O
9576 // (After this point, we shouldn't access AMS internal data structures.)
9577 Thread worker = new Thread("Error dump: " + dropboxTag) {
9578 @Override
9579 public void run() {
9580 if (report != null) {
9581 sb.append(report);
9582 }
9583 if (logFile != null) {
9584 try {
9585 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9586 } catch (IOException e) {
9587 Slog.e(TAG, "Error reading " + logFile, e);
9588 }
9589 }
9590 if (crashInfo != null && crashInfo.stackTrace != null) {
9591 sb.append(crashInfo.stackTrace);
9592 }
9593
9594 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9595 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9596 if (lines > 0) {
9597 sb.append("\n");
9598
9599 // Merge several logcat streams, and take the last N lines
9600 InputStreamReader input = null;
9601 try {
9602 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9603 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9604 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9605
9606 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9607 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9608 input = new InputStreamReader(logcat.getInputStream());
9609
9610 int num;
9611 char[] buf = new char[8192];
9612 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9613 } catch (IOException e) {
9614 Slog.e(TAG, "Error running logcat", e);
9615 } finally {
9616 if (input != null) try { input.close(); } catch (IOException e) {}
9617 }
9618 }
9619
9620 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009621 }
Dan Egnora455d192010-03-12 08:52:28 -08009622 };
9623
9624 if (process == null || process.pid == MY_PID) {
9625 worker.run(); // We may be about to die -- need to run this synchronously
9626 } else {
9627 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009628 }
9629 }
9630
9631 /**
9632 * Bring up the "unexpected error" dialog box for a crashing app.
9633 * Deal with edge cases (intercepts from instrumented applications,
9634 * ActivityController, error intent receivers, that sort of thing).
9635 * @param r the application crashing
9636 * @param crashInfo describing the failure
9637 */
9638 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009639 long timeMillis = System.currentTimeMillis();
9640 String shortMsg = crashInfo.exceptionClassName;
9641 String longMsg = crashInfo.exceptionMessage;
9642 String stackTrace = crashInfo.stackTrace;
9643 if (shortMsg != null && longMsg != null) {
9644 longMsg = shortMsg + ": " + longMsg;
9645 } else if (shortMsg != null) {
9646 longMsg = shortMsg;
9647 }
9648
Dan Egnor60d87622009-12-16 16:32:58 -08009649 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009650 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009651 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652 try {
9653 String name = r != null ? r.processName : null;
9654 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009655 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009656 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009657 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009658 + " at watcher's request");
9659 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009660 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009661 }
9662 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009663 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009664 }
9665 }
9666
9667 final long origId = Binder.clearCallingIdentity();
9668
9669 // If this process is running instrumentation, finish it.
9670 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009671 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009672 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009673 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9674 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009675 Bundle info = new Bundle();
9676 info.putString("shortMsg", shortMsg);
9677 info.putString("longMsg", longMsg);
9678 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9679 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009680 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009681 }
9682
Dan Egnor60d87622009-12-16 16:32:58 -08009683 // If we can't identify the process or it's already exceeded its crash quota,
9684 // quit right away without showing a crash dialog.
9685 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009686 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009687 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009688 }
9689
9690 Message msg = Message.obtain();
9691 msg.what = SHOW_ERROR_MSG;
9692 HashMap data = new HashMap();
9693 data.put("result", result);
9694 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009695 msg.obj = data;
9696 mHandler.sendMessage(msg);
9697
9698 Binder.restoreCallingIdentity(origId);
9699 }
9700
9701 int res = result.get();
9702
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009703 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009704 synchronized (this) {
9705 if (r != null) {
9706 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9707 SystemClock.uptimeMillis());
9708 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009709 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009710 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009711 }
9712 }
9713
9714 if (appErrorIntent != null) {
9715 try {
9716 mContext.startActivity(appErrorIntent);
9717 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009718 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009721 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009722
9723 Intent createAppErrorIntentLocked(ProcessRecord r,
9724 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9725 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009726 if (report == null) {
9727 return null;
9728 }
9729 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9730 result.setComponent(r.errorReportReceiver);
9731 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9732 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9733 return result;
9734 }
9735
Dan Egnorb7f03672009-12-09 16:22:32 -08009736 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9737 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009738 if (r.errorReportReceiver == null) {
9739 return null;
9740 }
9741
9742 if (!r.crashing && !r.notResponding) {
9743 return null;
9744 }
9745
Dan Egnorb7f03672009-12-09 16:22:32 -08009746 ApplicationErrorReport report = new ApplicationErrorReport();
9747 report.packageName = r.info.packageName;
9748 report.installerPackageName = r.errorReportReceiver.getPackageName();
9749 report.processName = r.processName;
9750 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009751 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009752
Dan Egnorb7f03672009-12-09 16:22:32 -08009753 if (r.crashing) {
9754 report.type = ApplicationErrorReport.TYPE_CRASH;
9755 report.crashInfo = crashInfo;
9756 } else if (r.notResponding) {
9757 report.type = ApplicationErrorReport.TYPE_ANR;
9758 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009759
Dan Egnorb7f03672009-12-09 16:22:32 -08009760 report.anrInfo.activity = r.notRespondingReport.tag;
9761 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9762 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009763 }
9764
Dan Egnorb7f03672009-12-09 16:22:32 -08009765 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009766 }
9767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009768 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9769 // assume our apps are happy - lazy create the list
9770 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9771
9772 synchronized (this) {
9773
9774 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009775 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9776 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009777 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9778 // This one's in trouble, so we'll generate a report for it
9779 // crashes are higher priority (in case there's a crash *and* an anr)
9780 ActivityManager.ProcessErrorStateInfo report = null;
9781 if (app.crashing) {
9782 report = app.crashingReport;
9783 } else if (app.notResponding) {
9784 report = app.notRespondingReport;
9785 }
9786
9787 if (report != null) {
9788 if (errList == null) {
9789 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9790 }
9791 errList.add(report);
9792 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009793 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794 " crashing = " + app.crashing +
9795 " notResponding = " + app.notResponding);
9796 }
9797 }
9798 }
9799 }
9800
9801 return errList;
9802 }
9803
9804 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9805 // Lazy instantiation of list
9806 List<ActivityManager.RunningAppProcessInfo> runList = null;
9807 synchronized (this) {
9808 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009809 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9810 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009811 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9812 // Generate process state info for running application
9813 ActivityManager.RunningAppProcessInfo currApp =
9814 new ActivityManager.RunningAppProcessInfo(app.processName,
9815 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009816 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009817 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009818 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009819 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9820 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9821 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009822 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9823 } else if (adj >= HOME_APP_ADJ) {
9824 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9825 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009826 } else if (adj >= SECONDARY_SERVER_ADJ) {
9827 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07009828 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
9829 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
9830 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
9831 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832 } else if (adj >= VISIBLE_APP_ADJ) {
9833 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9834 } else {
9835 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9836 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009837 currApp.importanceReasonCode = app.adjTypeCode;
9838 if (app.adjSource instanceof ProcessRecord) {
9839 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9840 } else if (app.adjSource instanceof HistoryRecord) {
9841 HistoryRecord r = (HistoryRecord)app.adjSource;
9842 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9843 }
9844 if (app.adjTarget instanceof ComponentName) {
9845 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9846 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009847 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009848 // + " lru=" + currApp.lru);
9849 if (runList == null) {
9850 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9851 }
9852 runList.add(currApp);
9853 }
9854 }
9855 }
9856 return runList;
9857 }
9858
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009859 public List<ApplicationInfo> getRunningExternalApplications() {
9860 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9861 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9862 if (runningApps != null && runningApps.size() > 0) {
9863 Set<String> extList = new HashSet<String>();
9864 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9865 if (app.pkgList != null) {
9866 for (String pkg : app.pkgList) {
9867 extList.add(pkg);
9868 }
9869 }
9870 }
9871 IPackageManager pm = ActivityThread.getPackageManager();
9872 for (String pkg : extList) {
9873 try {
9874 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9875 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9876 retList.add(info);
9877 }
9878 } catch (RemoteException e) {
9879 }
9880 }
9881 }
9882 return retList;
9883 }
9884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009885 @Override
9886 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009887 if (checkCallingPermission(android.Manifest.permission.DUMP)
9888 != PackageManager.PERMISSION_GRANTED) {
9889 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9890 + Binder.getCallingPid()
9891 + ", uid=" + Binder.getCallingUid()
9892 + " without permission "
9893 + android.Manifest.permission.DUMP);
9894 return;
9895 }
9896
9897 boolean dumpAll = false;
9898
9899 int opti = 0;
9900 while (opti < args.length) {
9901 String opt = args[opti];
9902 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9903 break;
9904 }
9905 opti++;
9906 if ("-a".equals(opt)) {
9907 dumpAll = true;
9908 } else if ("-h".equals(opt)) {
9909 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009910 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009911 pw.println(" cmd may be one of:");
9912 pw.println(" activities: activity stack state");
9913 pw.println(" broadcasts: broadcast state");
9914 pw.println(" intents: pending intent state");
9915 pw.println(" processes: process state");
9916 pw.println(" providers: content provider state");
9917 pw.println(" services: service state");
9918 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009919 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009920 } else {
9921 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009923 }
9924
9925 // Is the caller requesting to dump a particular piece of data?
9926 if (opti < args.length) {
9927 String cmd = args[opti];
9928 opti++;
9929 if ("activities".equals(cmd) || "a".equals(cmd)) {
9930 synchronized (this) {
9931 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009932 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009933 return;
9934 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9935 synchronized (this) {
9936 dumpBroadcastsLocked(fd, pw, args, opti, true);
9937 }
9938 return;
9939 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9940 synchronized (this) {
9941 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9942 }
9943 return;
9944 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9945 synchronized (this) {
9946 dumpProcessesLocked(fd, pw, args, opti, true);
9947 }
9948 return;
9949 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9950 synchronized (this) {
9951 dumpProvidersLocked(fd, pw, args, opti, true);
9952 }
9953 return;
9954 } else if ("service".equals(cmd)) {
9955 dumpService(fd, pw, args, opti, true);
9956 return;
9957 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9958 synchronized (this) {
9959 dumpServicesLocked(fd, pw, args, opti, true);
9960 }
9961 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009963 }
9964
9965 // No piece of data specified, dump everything.
9966 synchronized (this) {
9967 boolean needSep;
9968 if (dumpAll) {
9969 pw.println("Providers in Current Activity Manager State:");
9970 }
9971 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9972 if (needSep) {
9973 pw.println(" ");
9974 }
9975 if (dumpAll) {
9976 pw.println("-------------------------------------------------------------------------------");
9977 pw.println("Broadcasts in Current Activity Manager State:");
9978 }
9979 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9980 if (needSep) {
9981 pw.println(" ");
9982 }
9983 if (dumpAll) {
9984 pw.println("-------------------------------------------------------------------------------");
9985 pw.println("Services in Current Activity Manager State:");
9986 }
9987 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9988 if (needSep) {
9989 pw.println(" ");
9990 }
9991 if (dumpAll) {
9992 pw.println("-------------------------------------------------------------------------------");
9993 pw.println("PendingIntents in Current Activity Manager State:");
9994 }
9995 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9996 if (needSep) {
9997 pw.println(" ");
9998 }
9999 if (dumpAll) {
10000 pw.println("-------------------------------------------------------------------------------");
10001 pw.println("Activities in Current Activity Manager State:");
10002 }
10003 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
10004 if (needSep) {
10005 pw.println(" ");
10006 }
10007 if (dumpAll) {
10008 pw.println("-------------------------------------------------------------------------------");
10009 pw.println("Processes in Current Activity Manager State:");
10010 }
10011 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
10012 }
10013 }
10014
10015 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10016 int opti, boolean dumpAll, boolean needHeader) {
10017 if (needHeader) {
10018 pw.println(" Activity stack:");
10019 }
10020 dumpHistoryList(pw, mHistory, " ", "Hist", true);
10021 pw.println(" ");
10022 pw.println(" Running activities (most recent first):");
10023 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
10024 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010025 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010026 pw.println(" Activities waiting for another to become visible:");
10027 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
10028 }
10029 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010030 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010031 pw.println(" Activities waiting to stop:");
10032 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
10033 }
10034 if (mFinishingActivities.size() > 0) {
10035 pw.println(" ");
10036 pw.println(" Activities waiting to finish:");
10037 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
10038 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010039
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010040 pw.println(" ");
10041 pw.println(" mPausingActivity: " + mPausingActivity);
10042 pw.println(" mResumedActivity: " + mResumedActivity);
10043 pw.println(" mFocusedActivity: " + mFocusedActivity);
10044 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010045
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010046 if (dumpAll && mRecentTasks.size() > 0) {
10047 pw.println(" ");
10048 pw.println("Recent tasks in Current Activity Manager State:");
10049
10050 final int N = mRecentTasks.size();
10051 for (int i=0; i<N; i++) {
10052 TaskRecord tr = mRecentTasks.get(i);
10053 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
10054 pw.println(tr);
10055 mRecentTasks.get(i).dump(pw, " ");
10056 }
10057 }
10058
10059 pw.println(" ");
10060 pw.println(" mCurTask: " + mCurTask);
10061
10062 return true;
10063 }
10064
10065 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10066 int opti, boolean dumpAll) {
10067 boolean needSep = false;
10068 int numPers = 0;
10069
10070 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010071 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
10072 final int NA = procs.size();
10073 for (int ia=0; ia<NA; ia++) {
10074 if (!needSep) {
10075 pw.println(" All known processes:");
10076 needSep = true;
10077 }
10078 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010079 pw.print(r.persistent ? " *PERS*" : " *APP*");
10080 pw.print(" UID "); pw.print(procs.keyAt(ia));
10081 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010082 r.dump(pw, " ");
10083 if (r.persistent) {
10084 numPers++;
10085 }
10086 }
10087 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010088 }
10089
10090 if (mLruProcesses.size() > 0) {
10091 if (needSep) pw.println(" ");
10092 needSep = true;
10093 pw.println(" Running processes (most recent first):");
10094 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010095 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010096 needSep = true;
10097 }
10098
10099 synchronized (mPidsSelfLocked) {
10100 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010101 if (needSep) pw.println(" ");
10102 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010103 pw.println(" PID mappings:");
10104 for (int i=0; i<mPidsSelfLocked.size(); i++) {
10105 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
10106 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010107 }
10108 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010109 }
10110
10111 if (mForegroundProcesses.size() > 0) {
10112 if (needSep) pw.println(" ");
10113 needSep = true;
10114 pw.println(" Foreground Processes:");
10115 for (int i=0; i<mForegroundProcesses.size(); i++) {
10116 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
10117 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010118 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010119 }
10120
10121 if (mPersistentStartingProcesses.size() > 0) {
10122 if (needSep) pw.println(" ");
10123 needSep = true;
10124 pw.println(" Persisent processes that are starting:");
10125 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
10126 "Starting Norm", "Restarting PERS", false);
10127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010128
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010129 if (mStartingProcesses.size() > 0) {
10130 if (needSep) pw.println(" ");
10131 needSep = true;
10132 pw.println(" Processes that are starting:");
10133 dumpProcessList(pw, this, mStartingProcesses, " ",
10134 "Starting Norm", "Starting PERS", false);
10135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010136
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010137 if (mRemovedProcesses.size() > 0) {
10138 if (needSep) pw.println(" ");
10139 needSep = true;
10140 pw.println(" Processes that are being removed:");
10141 dumpProcessList(pw, this, mRemovedProcesses, " ",
10142 "Removed Norm", "Removed PERS", false);
10143 }
10144
10145 if (mProcessesOnHold.size() > 0) {
10146 if (needSep) pw.println(" ");
10147 needSep = true;
10148 pw.println(" Processes that are on old until the system is ready:");
10149 dumpProcessList(pw, this, mProcessesOnHold, " ",
10150 "OnHold Norm", "OnHold PERS", false);
10151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010152
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010153 if (mProcessesToGc.size() > 0) {
10154 if (needSep) pw.println(" ");
10155 needSep = true;
10156 pw.println(" Processes that are waiting to GC:");
10157 long now = SystemClock.uptimeMillis();
10158 for (int i=0; i<mProcessesToGc.size(); i++) {
10159 ProcessRecord proc = mProcessesToGc.get(i);
10160 pw.print(" Process "); pw.println(proc);
10161 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
10162 pw.print(", last gced=");
10163 pw.print(now-proc.lastRequestedGc);
10164 pw.print(" ms ago, last lowMem=");
10165 pw.print(now-proc.lastLowMemory);
10166 pw.println(" ms ago");
10167
10168 }
10169 }
10170
10171 if (mProcessCrashTimes.getMap().size() > 0) {
10172 if (needSep) pw.println(" ");
10173 needSep = true;
10174 pw.println(" Time since processes crashed:");
10175 long now = SystemClock.uptimeMillis();
10176 for (Map.Entry<String, SparseArray<Long>> procs
10177 : mProcessCrashTimes.getMap().entrySet()) {
10178 SparseArray<Long> uids = procs.getValue();
10179 final int N = uids.size();
10180 for (int i=0; i<N; i++) {
10181 pw.print(" Process "); pw.print(procs.getKey());
10182 pw.print(" uid "); pw.print(uids.keyAt(i));
10183 pw.print(": last crashed ");
10184 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010185 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010186 }
10187 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010189
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010190 if (mBadProcesses.getMap().size() > 0) {
10191 if (needSep) pw.println(" ");
10192 needSep = true;
10193 pw.println(" Bad processes:");
10194 for (Map.Entry<String, SparseArray<Long>> procs
10195 : mBadProcesses.getMap().entrySet()) {
10196 SparseArray<Long> uids = procs.getValue();
10197 final int N = uids.size();
10198 for (int i=0; i<N; i++) {
10199 pw.print(" Bad process "); pw.print(procs.getKey());
10200 pw.print(" uid "); pw.print(uids.keyAt(i));
10201 pw.print(": crashed at time ");
10202 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010203 }
10204 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010206
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010207 pw.println(" ");
10208 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010209 if (mHeavyWeightProcess != null) {
10210 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
10211 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010212 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -070010213 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010214 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
10215 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
10216 || mOrigWaitForDebugger) {
10217 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
10218 + " mDebugTransient=" + mDebugTransient
10219 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
10220 }
10221 if (mAlwaysFinishActivities || mController != null) {
10222 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
10223 + " mController=" + mController);
10224 }
10225 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010226 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010227 pw.println(" mStartRunning=" + mStartRunning
10228 + " mSystemReady=" + mSystemReady
10229 + " mBooting=" + mBooting
10230 + " mBooted=" + mBooted
10231 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010232 pw.println(" mGoingToSleep=" + mGoingToSleep);
10233 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -070010234 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010235 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010236
10237 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010238 }
10239
10240 /**
10241 * There are three ways to call this:
10242 * - no service specified: dump all the services
10243 * - a flattened component name that matched an existing service was specified as the
10244 * first arg: dump that one service
10245 * - the first arg isn't the flattened component name of an existing service:
10246 * dump all services whose component contains the first arg as a substring
10247 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010248 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
10249 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010250 String[] newArgs;
10251 String componentNameString;
10252 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -080010253 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010254 componentNameString = null;
10255 newArgs = EMPTY_STRING_ARRAY;
10256 r = null;
10257 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010258 componentNameString = args[opti];
10259 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010260 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
10261 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010262 newArgs = new String[args.length - opti];
10263 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010264 }
10265
10266 if (r != null) {
10267 dumpService(fd, pw, r, newArgs);
10268 } else {
10269 for (ServiceRecord r1 : mServices.values()) {
10270 if (componentNameString == null
10271 || r1.name.flattenToString().contains(componentNameString)) {
10272 dumpService(fd, pw, r1, newArgs);
10273 }
10274 }
10275 }
10276 }
10277
10278 /**
10279 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
10280 * there is a thread associated with the service.
10281 */
10282 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
10283 pw.println(" Service " + r.name.flattenToString());
10284 if (r.app != null && r.app.thread != null) {
10285 try {
10286 // flush anything that is already in the PrintWriter since the thread is going
10287 // to write to the file descriptor directly
10288 pw.flush();
10289 r.app.thread.dumpService(fd, r, args);
10290 pw.print("\n");
10291 } catch (RemoteException e) {
10292 pw.println("got a RemoteException while dumping the service");
10293 }
10294 }
10295 }
10296
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010297 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10298 int opti, boolean dumpAll) {
10299 boolean needSep = false;
10300
10301 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010302 if (mRegisteredReceivers.size() > 0) {
10303 pw.println(" ");
10304 pw.println(" Registered Receivers:");
10305 Iterator it = mRegisteredReceivers.values().iterator();
10306 while (it.hasNext()) {
10307 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010308 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010309 r.dump(pw, " ");
10310 }
10311 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010313 pw.println(" ");
10314 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010315 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010316 needSep = true;
10317 }
10318
10319 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
10320 || mPendingBroadcast != null) {
10321 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010322 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010323 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010324 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010325 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10326 pw.println(" Broadcast #" + i + ":");
10327 mParallelBroadcasts.get(i).dump(pw, " ");
10328 }
10329 if (mOrderedBroadcasts.size() > 0) {
10330 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010331 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010332 }
10333 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10334 pw.println(" Serialized Broadcast #" + i + ":");
10335 mOrderedBroadcasts.get(i).dump(pw, " ");
10336 }
10337 pw.println(" ");
10338 pw.println(" Pending broadcast:");
10339 if (mPendingBroadcast != null) {
10340 mPendingBroadcast.dump(pw, " ");
10341 } else {
10342 pw.println(" (null)");
10343 }
10344 needSep = true;
10345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010346
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010347 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010348 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -080010349 pw.println(" Historical broadcasts:");
10350 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
10351 BroadcastRecord r = mBroadcastHistory[i];
10352 if (r == null) {
10353 break;
10354 }
10355 pw.println(" Historical Broadcast #" + i + ":");
10356 r.dump(pw, " ");
10357 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010358 needSep = true;
10359 }
10360
10361 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010362 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010363 pw.println(" Sticky broadcasts:");
10364 StringBuilder sb = new StringBuilder(128);
10365 for (Map.Entry<String, ArrayList<Intent>> ent
10366 : mStickyBroadcasts.entrySet()) {
10367 pw.print(" * Sticky action "); pw.print(ent.getKey());
10368 pw.println(":");
10369 ArrayList<Intent> intents = ent.getValue();
10370 final int N = intents.size();
10371 for (int i=0; i<N; i++) {
10372 sb.setLength(0);
10373 sb.append(" Intent: ");
10374 intents.get(i).toShortString(sb, true, false);
10375 pw.println(sb.toString());
10376 Bundle bundle = intents.get(i).getExtras();
10377 if (bundle != null) {
10378 pw.print(" ");
10379 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010380 }
10381 }
10382 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010383 needSep = true;
10384 }
10385
10386 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010387 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010388 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010389 pw.println(" mHandler:");
10390 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010391 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010392 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010393
10394 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010395 }
10396
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010397 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10398 int opti, boolean dumpAll) {
10399 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010400
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010401 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010402 if (mServices.size() > 0) {
10403 pw.println(" Active services:");
10404 Iterator<ServiceRecord> it = mServices.values().iterator();
10405 while (it.hasNext()) {
10406 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010407 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010408 r.dump(pw, " ");
10409 }
10410 needSep = true;
10411 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010413
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010414 if (mPendingServices.size() > 0) {
10415 if (needSep) pw.println(" ");
10416 pw.println(" Pending services:");
10417 for (int i=0; i<mPendingServices.size(); i++) {
10418 ServiceRecord r = mPendingServices.get(i);
10419 pw.print(" * Pending "); pw.println(r);
10420 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010421 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010422 needSep = true;
10423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010424
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010425 if (mRestartingServices.size() > 0) {
10426 if (needSep) pw.println(" ");
10427 pw.println(" Restarting services:");
10428 for (int i=0; i<mRestartingServices.size(); i++) {
10429 ServiceRecord r = mRestartingServices.get(i);
10430 pw.print(" * Restarting "); pw.println(r);
10431 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010432 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010433 needSep = true;
10434 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010436 if (mStoppingServices.size() > 0) {
10437 if (needSep) pw.println(" ");
10438 pw.println(" Stopping services:");
10439 for (int i=0; i<mStoppingServices.size(); i++) {
10440 ServiceRecord r = mStoppingServices.get(i);
10441 pw.print(" * Stopping "); pw.println(r);
10442 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010444 needSep = true;
10445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010447 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010448 if (mServiceConnections.size() > 0) {
10449 if (needSep) pw.println(" ");
10450 pw.println(" Connection bindings to services:");
10451 Iterator<ConnectionRecord> it
10452 = mServiceConnections.values().iterator();
10453 while (it.hasNext()) {
10454 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010455 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456 r.dump(pw, " ");
10457 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010458 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010459 }
10460 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010461
10462 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010463 }
10464
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010465 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10466 int opti, boolean dumpAll) {
10467 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010468
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010469 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010470 if (mProvidersByClass.size() > 0) {
10471 if (needSep) pw.println(" ");
10472 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010473 Iterator<Map.Entry<String, ContentProviderRecord>> it
10474 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010475 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010476 Map.Entry<String, ContentProviderRecord> e = it.next();
10477 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010478 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 r.dump(pw, " ");
10480 }
10481 needSep = true;
10482 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010483
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010484 if (mProvidersByName.size() > 0) {
10485 pw.println(" ");
10486 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010487 Iterator<Map.Entry<String, ContentProviderRecord>> it
10488 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010489 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010490 Map.Entry<String, ContentProviderRecord> e = it.next();
10491 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010492 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10493 pw.println(r);
10494 }
10495 needSep = true;
10496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010497 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010498
10499 if (mLaunchingProviders.size() > 0) {
10500 if (needSep) pw.println(" ");
10501 pw.println(" Launching content providers:");
10502 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10503 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10504 pw.println(mLaunchingProviders.get(i));
10505 }
10506 needSep = true;
10507 }
10508
10509 if (mGrantedUriPermissions.size() > 0) {
10510 pw.println();
10511 pw.println("Granted Uri Permissions:");
10512 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10513 int uid = mGrantedUriPermissions.keyAt(i);
10514 HashMap<Uri, UriPermission> perms
10515 = mGrantedUriPermissions.valueAt(i);
10516 pw.print(" * UID "); pw.print(uid);
10517 pw.println(" holds:");
10518 for (UriPermission perm : perms.values()) {
10519 pw.print(" "); pw.println(perm);
10520 perm.dump(pw, " ");
10521 }
10522 }
10523 needSep = true;
10524 }
10525
10526 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010527 }
10528
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010529 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10530 int opti, boolean dumpAll) {
10531 boolean needSep = false;
10532
10533 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010534 if (this.mIntentSenderRecords.size() > 0) {
10535 Iterator<WeakReference<PendingIntentRecord>> it
10536 = mIntentSenderRecords.values().iterator();
10537 while (it.hasNext()) {
10538 WeakReference<PendingIntentRecord> ref = it.next();
10539 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010540 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010541 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010542 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010543 rec.dump(pw, " ");
10544 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010545 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 }
10547 }
10548 }
10549 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010550
10551 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010552 }
10553
10554 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010555 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010556 TaskRecord lastTask = null;
10557 for (int i=list.size()-1; i>=0; i--) {
10558 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010559 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010560 if (lastTask != r.task) {
10561 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010562 pw.print(prefix);
10563 pw.print(full ? "* " : " ");
10564 pw.println(lastTask);
10565 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010566 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010569 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10570 pw.print(" #"); pw.print(i); pw.print(": ");
10571 pw.println(r);
10572 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010573 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010575 }
10576 }
10577
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010578 private static String buildOomTag(String prefix, String space, int val, int base) {
10579 if (val == base) {
10580 if (space == null) return prefix;
10581 return prefix + " ";
10582 }
10583 return prefix + "+" + Integer.toString(val-base);
10584 }
10585
10586 private static final int dumpProcessList(PrintWriter pw,
10587 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010588 String prefix, String normalLabel, String persistentLabel,
10589 boolean inclOomAdj) {
10590 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010591 final int N = list.size()-1;
10592 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010593 ProcessRecord r = (ProcessRecord)list.get(i);
10594 if (false) {
10595 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10596 + " #" + i + ":");
10597 r.dump(pw, prefix + " ");
10598 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010599 String oomAdj;
10600 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010601 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010602 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010603 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10604 } else if (r.setAdj >= HOME_APP_ADJ) {
10605 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10606 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10607 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10608 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10609 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010610 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
10611 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
10612 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
10613 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010614 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10615 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10616 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10617 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010618 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010619 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010620 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010621 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010622 } else {
10623 oomAdj = Integer.toString(r.setAdj);
10624 }
10625 String schedGroup;
10626 switch (r.setSchedGroup) {
10627 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10628 schedGroup = "B";
10629 break;
10630 case Process.THREAD_GROUP_DEFAULT:
10631 schedGroup = "F";
10632 break;
10633 default:
10634 schedGroup = Integer.toString(r.setSchedGroup);
10635 break;
10636 }
10637 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010638 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010639 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010640 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010641 pw.print(prefix);
10642 pw.print(" ");
10643 if (r.adjTarget instanceof ComponentName) {
10644 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
10645 } else if (r.adjTarget != null) {
10646 pw.print(r.adjTarget.toString());
10647 } else {
10648 pw.print("{null}");
10649 }
10650 pw.print("<=");
10651 if (r.adjSource instanceof ProcessRecord) {
10652 pw.print("Proc{");
10653 pw.print(((ProcessRecord)r.adjSource).toShortString());
10654 pw.println("}");
10655 } else if (r.adjSource != null) {
10656 pw.println(r.adjSource.toString());
10657 } else {
10658 pw.println("{null}");
10659 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010661 } else {
10662 pw.println(String.format("%s%s #%2d: %s",
10663 prefix, (r.persistent ? persistentLabel : normalLabel),
10664 i, r.toString()));
10665 }
10666 if (r.persistent) {
10667 numPers++;
10668 }
10669 }
10670 return numPers;
10671 }
10672
Dianne Hackborn472ad872010-04-07 17:31:48 -070010673 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010674 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010675 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010676 long uptime = SystemClock.uptimeMillis();
10677 long realtime = SystemClock.elapsedRealtime();
10678
10679 if (isCheckinRequest) {
10680 // short checkin version
10681 pw.println(uptime + "," + realtime);
10682 pw.flush();
10683 } else {
10684 pw.println("Applications Memory Usage (kB):");
10685 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10686 }
10687 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10688 ProcessRecord r = (ProcessRecord)list.get(i);
10689 if (r.thread != null) {
10690 if (!isCheckinRequest) {
10691 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10692 pw.flush();
10693 }
10694 try {
10695 r.thread.asBinder().dump(fd, args);
10696 } catch (RemoteException e) {
10697 if (!isCheckinRequest) {
10698 pw.println("Got RemoteException!");
10699 pw.flush();
10700 }
10701 }
10702 }
10703 }
10704 }
10705
10706 /**
10707 * Searches array of arguments for the specified string
10708 * @param args array of argument strings
10709 * @param value value to search for
10710 * @return true if the value is contained in the array
10711 */
10712 private static boolean scanArgs(String[] args, String value) {
10713 if (args != null) {
10714 for (String arg : args) {
10715 if (value.equals(arg)) {
10716 return true;
10717 }
10718 }
10719 }
10720 return false;
10721 }
10722
Dianne Hackborn75b03852009-06-12 15:43:26 -070010723 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010724 int count = mHistory.size();
10725
10726 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010727 int index = -1;
10728 for (int i=count-1; i>=0; i--) {
10729 Object o = mHistory.get(i);
10730 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010731 index = i;
10732 break;
10733 }
10734 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010735
10736 return index;
10737 }
10738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010739 private final void killServicesLocked(ProcessRecord app,
10740 boolean allowRestart) {
10741 // Report disconnected services.
10742 if (false) {
10743 // XXX we are letting the client link to the service for
10744 // death notifications.
10745 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010746 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010747 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010748 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010749 if (r.connections.size() > 0) {
10750 Iterator<ConnectionRecord> jt
10751 = r.connections.values().iterator();
10752 while (jt.hasNext()) {
10753 ConnectionRecord c = jt.next();
10754 if (c.binding.client != app) {
10755 try {
10756 //c.conn.connected(r.className, null);
10757 } catch (Exception e) {
10758 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010759 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010760 + r.shortName
10761 + " from app " + app.processName, e);
10762 }
10763 }
10764 }
10765 }
10766 }
10767 }
10768 }
10769
10770 // Clean up any connections this application has to other services.
10771 if (app.connections.size() > 0) {
10772 Iterator<ConnectionRecord> it = app.connections.iterator();
10773 while (it.hasNext()) {
10774 ConnectionRecord r = it.next();
10775 removeConnectionLocked(r, app, null);
10776 }
10777 }
10778 app.connections.clear();
10779
10780 if (app.services.size() != 0) {
10781 // Any services running in the application need to be placed
10782 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010783 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010784 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010785 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010786 synchronized (sr.stats.getBatteryStats()) {
10787 sr.stats.stopLaunchedLocked();
10788 }
10789 sr.app = null;
10790 sr.executeNesting = 0;
10791 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010792
10793 boolean hasClients = sr.bindings.size() > 0;
10794 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010795 Iterator<IntentBindRecord> bindings
10796 = sr.bindings.values().iterator();
10797 while (bindings.hasNext()) {
10798 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010799 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010800 + ": shouldUnbind=" + b.hasBound);
10801 b.binder = null;
10802 b.requested = b.received = b.hasBound = false;
10803 }
10804 }
10805
10806 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010807 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010808 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010809 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010810 sr.crashCount, sr.shortName, app.pid);
10811 bringDownServiceLocked(sr, true);
10812 } else if (!allowRestart) {
10813 bringDownServiceLocked(sr, true);
10814 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010815 boolean canceled = scheduleServiceRestartLocked(sr, true);
10816
10817 // Should the service remain running? Note that in the
10818 // extreme case of so many attempts to deliver a command
10819 // that it failed, that we also will stop it here.
10820 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10821 if (sr.pendingStarts.size() == 0) {
10822 sr.startRequested = false;
10823 if (!hasClients) {
10824 // Whoops, no reason to restart!
10825 bringDownServiceLocked(sr, true);
10826 }
10827 }
10828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829 }
10830 }
10831
10832 if (!allowRestart) {
10833 app.services.clear();
10834 }
10835 }
10836
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010837 // Make sure we have no more records on the stopping list.
10838 int i = mStoppingServices.size();
10839 while (i > 0) {
10840 i--;
10841 ServiceRecord sr = mStoppingServices.get(i);
10842 if (sr.app == app) {
10843 mStoppingServices.remove(i);
10844 }
10845 }
10846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010847 app.executingServices.clear();
10848 }
10849
10850 private final void removeDyingProviderLocked(ProcessRecord proc,
10851 ContentProviderRecord cpr) {
10852 synchronized (cpr) {
10853 cpr.launchingApp = null;
10854 cpr.notifyAll();
10855 }
10856
10857 mProvidersByClass.remove(cpr.info.name);
10858 String names[] = cpr.info.authority.split(";");
10859 for (int j = 0; j < names.length; j++) {
10860 mProvidersByName.remove(names[j]);
10861 }
10862
10863 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10864 while (cit.hasNext()) {
10865 ProcessRecord capp = cit.next();
10866 if (!capp.persistent && capp.thread != null
10867 && capp.pid != 0
10868 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010869 Slog.i(TAG, "Kill " + capp.processName
10870 + " (pid " + capp.pid + "): provider " + cpr.info.name
10871 + " in dying process " + proc.processName);
10872 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10873 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010874 Process.killProcess(capp.pid);
10875 }
10876 }
10877
10878 mLaunchingProviders.remove(cpr);
10879 }
10880
10881 /**
10882 * Main code for cleaning up a process when it has gone away. This is
10883 * called both as a result of the process dying, or directly when stopping
10884 * a process when running in single process mode.
10885 */
10886 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10887 boolean restarting, int index) {
10888 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010889 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010890 }
10891
Dianne Hackborn36124872009-10-08 16:22:03 -070010892 mProcessesToGc.remove(app);
10893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 // Dismiss any open dialogs.
10895 if (app.crashDialog != null) {
10896 app.crashDialog.dismiss();
10897 app.crashDialog = null;
10898 }
10899 if (app.anrDialog != null) {
10900 app.anrDialog.dismiss();
10901 app.anrDialog = null;
10902 }
10903 if (app.waitDialog != null) {
10904 app.waitDialog.dismiss();
10905 app.waitDialog = null;
10906 }
10907
10908 app.crashing = false;
10909 app.notResponding = false;
10910
10911 app.resetPackageList();
10912 app.thread = null;
10913 app.forcingToForeground = null;
10914 app.foregroundServices = false;
10915
10916 killServicesLocked(app, true);
10917
10918 boolean restart = false;
10919
10920 int NL = mLaunchingProviders.size();
10921
10922 // Remove published content providers.
10923 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010924 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010925 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010926 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927 cpr.provider = null;
10928 cpr.app = null;
10929
10930 // See if someone is waiting for this provider... in which
10931 // case we don't remove it, but just let it restart.
10932 int i = 0;
10933 if (!app.bad) {
10934 for (; i<NL; i++) {
10935 if (mLaunchingProviders.get(i) == cpr) {
10936 restart = true;
10937 break;
10938 }
10939 }
10940 } else {
10941 i = NL;
10942 }
10943
10944 if (i >= NL) {
10945 removeDyingProviderLocked(app, cpr);
10946 NL = mLaunchingProviders.size();
10947 }
10948 }
10949 app.pubProviders.clear();
10950 }
10951
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010952 // Take care of any launching providers waiting for this process.
10953 if (checkAppInLaunchingProvidersLocked(app, false)) {
10954 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010955 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010957 // Unregister from connected content providers.
10958 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010959 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 while (it.hasNext()) {
10961 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10962 cpr.clients.remove(app);
10963 }
10964 app.conProviders.clear();
10965 }
10966
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010967 // At this point there may be remaining entries in mLaunchingProviders
10968 // where we were the only one waiting, so they are no longer of use.
10969 // Look for these and clean up if found.
10970 // XXX Commented out for now. Trying to figure out a way to reproduce
10971 // the actual situation to identify what is actually going on.
10972 if (false) {
10973 for (int i=0; i<NL; i++) {
10974 ContentProviderRecord cpr = (ContentProviderRecord)
10975 mLaunchingProviders.get(i);
10976 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10977 synchronized (cpr) {
10978 cpr.launchingApp = null;
10979 cpr.notifyAll();
10980 }
10981 }
10982 }
10983 }
10984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 skipCurrentReceiverLocked(app);
10986
10987 // Unregister any receivers.
10988 if (app.receivers.size() > 0) {
10989 Iterator<ReceiverList> it = app.receivers.iterator();
10990 while (it.hasNext()) {
10991 removeReceiverLocked(it.next());
10992 }
10993 app.receivers.clear();
10994 }
10995
Christopher Tate181fafa2009-05-14 11:12:14 -070010996 // If the app is undergoing backup, tell the backup manager about it
10997 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010998 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010999 try {
11000 IBackupManager bm = IBackupManager.Stub.asInterface(
11001 ServiceManager.getService(Context.BACKUP_SERVICE));
11002 bm.agentDisconnected(app.info.packageName);
11003 } catch (RemoteException e) {
11004 // can't happen; backup manager is local
11005 }
11006 }
11007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 // If the caller is restarting this app, then leave it in its
11009 // current lists and let the caller take care of it.
11010 if (restarting) {
11011 return;
11012 }
11013
11014 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011015 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016 "Removing non-persistent process during cleanup: " + app);
11017 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070011018 if (mHeavyWeightProcess == app) {
11019 mHeavyWeightProcess = null;
11020 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
11021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011022 } else if (!app.removed) {
11023 // This app is persistent, so we need to keep its record around.
11024 // If it is not already on the pending app list, add it there
11025 // and start a new process for it.
11026 app.thread = null;
11027 app.forcingToForeground = null;
11028 app.foregroundServices = false;
11029 if (mPersistentStartingProcesses.indexOf(app) < 0) {
11030 mPersistentStartingProcesses.add(app);
11031 restart = true;
11032 }
11033 }
11034 mProcessesOnHold.remove(app);
11035
The Android Open Source Project4df24232009-03-05 14:34:35 -080011036 if (app == mHomeProcess) {
11037 mHomeProcess = null;
11038 }
11039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011040 if (restart) {
11041 // We have components that still need to be running in the
11042 // process, so re-launch it.
11043 mProcessNames.put(app.processName, app.info.uid, app);
11044 startProcessLocked(app, "restart", app.processName);
11045 } else if (app.pid > 0 && app.pid != MY_PID) {
11046 // Goodbye!
11047 synchronized (mPidsSelfLocked) {
11048 mPidsSelfLocked.remove(app.pid);
11049 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
11050 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070011051 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052 }
11053 }
11054
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011055 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
11056 // Look through the content providers we are waiting to have launched,
11057 // and if any run in this process then either schedule a restart of
11058 // the process or kill the client waiting for it if this process has
11059 // gone bad.
11060 int NL = mLaunchingProviders.size();
11061 boolean restart = false;
11062 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011063 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011064 if (cpr.launchingApp == app) {
11065 if (!alwaysBad && !app.bad) {
11066 restart = true;
11067 } else {
11068 removeDyingProviderLocked(app, cpr);
11069 NL = mLaunchingProviders.size();
11070 }
11071 }
11072 }
11073 return restart;
11074 }
11075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011076 // =========================================================
11077 // SERVICES
11078 // =========================================================
11079
11080 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
11081 ActivityManager.RunningServiceInfo info =
11082 new ActivityManager.RunningServiceInfo();
11083 info.service = r.name;
11084 if (r.app != null) {
11085 info.pid = r.app.pid;
11086 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011087 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011088 info.process = r.processName;
11089 info.foreground = r.isForeground;
11090 info.activeSince = r.createTime;
11091 info.started = r.startRequested;
11092 info.clientCount = r.connections.size();
11093 info.crashCount = r.crashCount;
11094 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011095 if (r.isForeground) {
11096 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
11097 }
11098 if (r.startRequested) {
11099 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
11100 }
Dan Egnor42471dd2010-01-07 17:25:22 -080011101 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011102 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
11103 }
11104 if (r.app != null && r.app.persistent) {
11105 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
11106 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011107 for (ConnectionRecord conn : r.connections.values()) {
11108 if (conn.clientLabel != 0) {
11109 info.clientPackage = conn.binding.client.info.packageName;
11110 info.clientLabel = conn.clientLabel;
11111 break;
11112 }
11113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011114 return info;
11115 }
11116
11117 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
11118 int flags) {
11119 synchronized (this) {
11120 ArrayList<ActivityManager.RunningServiceInfo> res
11121 = new ArrayList<ActivityManager.RunningServiceInfo>();
11122
11123 if (mServices.size() > 0) {
11124 Iterator<ServiceRecord> it = mServices.values().iterator();
11125 while (it.hasNext() && res.size() < maxNum) {
11126 res.add(makeRunningServiceInfoLocked(it.next()));
11127 }
11128 }
11129
11130 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
11131 ServiceRecord r = mRestartingServices.get(i);
11132 ActivityManager.RunningServiceInfo info =
11133 makeRunningServiceInfoLocked(r);
11134 info.restarting = r.nextRestartTime;
11135 res.add(info);
11136 }
11137
11138 return res;
11139 }
11140 }
11141
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011142 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
11143 synchronized (this) {
11144 ServiceRecord r = mServices.get(name);
11145 if (r != null) {
11146 for (ConnectionRecord conn : r.connections.values()) {
11147 if (conn.clientIntent != null) {
11148 return conn.clientIntent;
11149 }
11150 }
11151 }
11152 }
11153 return null;
11154 }
11155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 private final ServiceRecord findServiceLocked(ComponentName name,
11157 IBinder token) {
11158 ServiceRecord r = mServices.get(name);
11159 return r == token ? r : null;
11160 }
11161
11162 private final class ServiceLookupResult {
11163 final ServiceRecord record;
11164 final String permission;
11165
11166 ServiceLookupResult(ServiceRecord _record, String _permission) {
11167 record = _record;
11168 permission = _permission;
11169 }
11170 };
11171
11172 private ServiceLookupResult findServiceLocked(Intent service,
11173 String resolvedType) {
11174 ServiceRecord r = null;
11175 if (service.getComponent() != null) {
11176 r = mServices.get(service.getComponent());
11177 }
11178 if (r == null) {
11179 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11180 r = mServicesByIntent.get(filter);
11181 }
11182
11183 if (r == null) {
11184 try {
11185 ResolveInfo rInfo =
11186 ActivityThread.getPackageManager().resolveService(
11187 service, resolvedType, 0);
11188 ServiceInfo sInfo =
11189 rInfo != null ? rInfo.serviceInfo : null;
11190 if (sInfo == null) {
11191 return null;
11192 }
11193
11194 ComponentName name = new ComponentName(
11195 sInfo.applicationInfo.packageName, sInfo.name);
11196 r = mServices.get(name);
11197 } catch (RemoteException ex) {
11198 // pm is in same process, this will never happen.
11199 }
11200 }
11201 if (r != null) {
11202 int callingPid = Binder.getCallingPid();
11203 int callingUid = Binder.getCallingUid();
11204 if (checkComponentPermission(r.permission,
11205 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11206 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011207 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011208 + " from pid=" + callingPid
11209 + ", uid=" + callingUid
11210 + " requires " + r.permission);
11211 return new ServiceLookupResult(null, r.permission);
11212 }
11213 return new ServiceLookupResult(r, null);
11214 }
11215 return null;
11216 }
11217
11218 private class ServiceRestarter implements Runnable {
11219 private ServiceRecord mService;
11220
11221 void setService(ServiceRecord service) {
11222 mService = service;
11223 }
11224
11225 public void run() {
11226 synchronized(ActivityManagerService.this) {
11227 performServiceRestartLocked(mService);
11228 }
11229 }
11230 }
11231
11232 private ServiceLookupResult retrieveServiceLocked(Intent service,
11233 String resolvedType, int callingPid, int callingUid) {
11234 ServiceRecord r = null;
11235 if (service.getComponent() != null) {
11236 r = mServices.get(service.getComponent());
11237 }
11238 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11239 r = mServicesByIntent.get(filter);
11240 if (r == null) {
11241 try {
11242 ResolveInfo rInfo =
11243 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011244 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011245 ServiceInfo sInfo =
11246 rInfo != null ? rInfo.serviceInfo : null;
11247 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011248 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011249 ": not found");
11250 return null;
11251 }
11252
11253 ComponentName name = new ComponentName(
11254 sInfo.applicationInfo.packageName, sInfo.name);
11255 r = mServices.get(name);
11256 if (r == null) {
11257 filter = new Intent.FilterComparison(service.cloneFilter());
11258 ServiceRestarter res = new ServiceRestarter();
11259 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11260 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11261 synchronized (stats) {
11262 ss = stats.getServiceStatsLocked(
11263 sInfo.applicationInfo.uid, sInfo.packageName,
11264 sInfo.name);
11265 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080011266 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 res.setService(r);
11268 mServices.put(name, r);
11269 mServicesByIntent.put(filter, r);
11270
11271 // Make sure this component isn't in the pending list.
11272 int N = mPendingServices.size();
11273 for (int i=0; i<N; i++) {
11274 ServiceRecord pr = mPendingServices.get(i);
11275 if (pr.name.equals(name)) {
11276 mPendingServices.remove(i);
11277 i--;
11278 N--;
11279 }
11280 }
11281 }
11282 } catch (RemoteException ex) {
11283 // pm is in same process, this will never happen.
11284 }
11285 }
11286 if (r != null) {
11287 if (checkComponentPermission(r.permission,
11288 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11289 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011290 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291 + " from pid=" + Binder.getCallingPid()
11292 + ", uid=" + Binder.getCallingUid()
11293 + " requires " + r.permission);
11294 return new ServiceLookupResult(null, r.permission);
11295 }
11296 return new ServiceLookupResult(r, null);
11297 }
11298 return null;
11299 }
11300
11301 private final void bumpServiceExecutingLocked(ServiceRecord r) {
11302 long now = SystemClock.uptimeMillis();
11303 if (r.executeNesting == 0 && r.app != null) {
11304 if (r.app.executingServices.size() == 0) {
11305 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11306 msg.obj = r.app;
11307 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
11308 }
11309 r.app.executingServices.add(r);
11310 }
11311 r.executeNesting++;
11312 r.executingStart = now;
11313 }
11314
11315 private final void sendServiceArgsLocked(ServiceRecord r,
11316 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011317 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011318 if (N == 0) {
11319 return;
11320 }
11321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011322 int i = 0;
11323 while (i < N) {
11324 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011325 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011326 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011327 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070011328 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011329 // If somehow we got a dummy start at the front, then
11330 // just drop it here.
11331 i++;
11332 continue;
11333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334 bumpServiceExecutingLocked(r);
11335 if (!oomAdjusted) {
11336 oomAdjusted = true;
11337 updateOomAdjLocked(r.app);
11338 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011339 int flags = 0;
11340 if (si.deliveryCount > 0) {
11341 flags |= Service.START_FLAG_RETRY;
11342 }
11343 if (si.doneExecutingCount > 0) {
11344 flags |= Service.START_FLAG_REDELIVERY;
11345 }
11346 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
11347 si.deliveredTime = SystemClock.uptimeMillis();
11348 r.deliveredStarts.add(si);
11349 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011350 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011351 } catch (RemoteException e) {
11352 // Remote process gone... we'll let the normal cleanup take
11353 // care of this.
11354 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011355 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011356 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 break;
11358 }
11359 }
11360 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011361 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 } else {
11363 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011364 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011365 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011366 }
11367 }
11368 }
11369
11370 private final boolean requestServiceBindingLocked(ServiceRecord r,
11371 IntentBindRecord i, boolean rebind) {
11372 if (r.app == null || r.app.thread == null) {
11373 // If service is not currently running, can't yet bind.
11374 return false;
11375 }
11376 if ((!i.requested || rebind) && i.apps.size() > 0) {
11377 try {
11378 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011379 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011380 + ": shouldUnbind=" + i.hasBound);
11381 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11382 if (!rebind) {
11383 i.requested = true;
11384 }
11385 i.hasBound = true;
11386 i.doRebind = false;
11387 } catch (RemoteException e) {
11388 return false;
11389 }
11390 }
11391 return true;
11392 }
11393
11394 private final void requestServiceBindingsLocked(ServiceRecord r) {
11395 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11396 while (bindings.hasNext()) {
11397 IntentBindRecord i = bindings.next();
11398 if (!requestServiceBindingLocked(r, i, false)) {
11399 break;
11400 }
11401 }
11402 }
11403
11404 private final void realStartServiceLocked(ServiceRecord r,
11405 ProcessRecord app) throws RemoteException {
11406 if (app.thread == null) {
11407 throw new RemoteException();
11408 }
11409
11410 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011411 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011412
11413 app.services.add(r);
11414 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011415 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011416
11417 boolean created = false;
11418 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011419 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011420 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011421 mStringBuilder.setLength(0);
11422 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011423 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011424 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011425 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426 synchronized (r.stats.getBatteryStats()) {
11427 r.stats.startLaunchedLocked();
11428 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011429 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011430 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011431 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432 created = true;
11433 } finally {
11434 if (!created) {
11435 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011436 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011437 }
11438 }
11439
11440 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011441
11442 // If the service is in the started state, and there are no
11443 // pending arguments, then fake up one so its onStartCommand() will
11444 // be called.
11445 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11446 r.lastStartId++;
11447 if (r.lastStartId < 1) {
11448 r.lastStartId = 1;
11449 }
11450 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11451 }
11452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011453 sendServiceArgsLocked(r, true);
11454 }
11455
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011456 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11457 boolean allowCancel) {
11458 boolean canceled = false;
11459
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011460 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011461 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011462 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011463
11464 // Any delivered but not yet finished starts should be put back
11465 // on the pending list.
11466 final int N = r.deliveredStarts.size();
11467 if (N > 0) {
11468 for (int i=N-1; i>=0; i--) {
11469 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11470 if (si.intent == null) {
11471 // We'll generate this again if needed.
11472 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11473 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11474 r.pendingStarts.add(0, si);
11475 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11476 dur *= 2;
11477 if (minDuration < dur) minDuration = dur;
11478 if (resetTime < dur) resetTime = dur;
11479 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011480 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011481 + r.name);
11482 canceled = true;
11483 }
11484 }
11485 r.deliveredStarts.clear();
11486 }
11487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011488 r.totalRestartCount++;
11489 if (r.restartDelay == 0) {
11490 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011491 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011492 } else {
11493 // If it has been a "reasonably long time" since the service
11494 // was started, then reset our restart duration back to
11495 // the beginning, so we don't infinitely increase the duration
11496 // on a service that just occasionally gets killed (which is
11497 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011498 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011499 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011500 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011501 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011502 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011503 if (r.restartDelay < minDuration) {
11504 r.restartDelay = minDuration;
11505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011506 }
11507 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011508
11509 r.nextRestartTime = now + r.restartDelay;
11510
11511 // Make sure that we don't end up restarting a bunch of services
11512 // all at the same time.
11513 boolean repeat;
11514 do {
11515 repeat = false;
11516 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11517 ServiceRecord r2 = mRestartingServices.get(i);
11518 if (r2 != r && r.nextRestartTime
11519 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11520 && r.nextRestartTime
11521 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11522 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11523 r.restartDelay = r.nextRestartTime - now;
11524 repeat = true;
11525 break;
11526 }
11527 }
11528 } while (repeat);
11529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011530 if (!mRestartingServices.contains(r)) {
11531 mRestartingServices.add(r);
11532 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011533
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011534 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011536 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011537 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011538 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011539 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011540 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011541 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011542 r.shortName, r.restartDelay);
11543
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011544 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011545 }
11546
11547 final void performServiceRestartLocked(ServiceRecord r) {
11548 if (!mRestartingServices.contains(r)) {
11549 return;
11550 }
11551 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11552 }
11553
11554 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11555 if (r.restartDelay == 0) {
11556 return false;
11557 }
11558 r.resetRestartCounter();
11559 mRestartingServices.remove(r);
11560 mHandler.removeCallbacks(r.restarter);
11561 return true;
11562 }
11563
11564 private final boolean bringUpServiceLocked(ServiceRecord r,
11565 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011566 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011567 //r.dump(" ");
11568
Dianne Hackborn36124872009-10-08 16:22:03 -070011569 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011570 sendServiceArgsLocked(r, false);
11571 return true;
11572 }
11573
11574 if (!whileRestarting && r.restartDelay > 0) {
11575 // If waiting for a restart, then do nothing.
11576 return true;
11577 }
11578
Joe Onorato8a9b2202010-02-26 18:56:32 -080011579 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011580 + " " + r.intent);
11581
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011582 // We are now bringing the service up, so no longer in the
11583 // restarting state.
11584 mRestartingServices.remove(r);
11585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011586 final String appName = r.processName;
11587 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11588 if (app != null && app.thread != null) {
11589 try {
11590 realStartServiceLocked(r, app);
11591 return true;
11592 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011593 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 }
11595
11596 // If a dead object exception was thrown -- fall through to
11597 // restart the application.
11598 }
11599
Dianne Hackborn36124872009-10-08 16:22:03 -070011600 // Not running -- get it started, and enqueue this service record
11601 // to be executed when the app comes up.
11602 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11603 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011604 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011605 + r.appInfo.packageName + "/"
11606 + r.appInfo.uid + " for service "
11607 + r.intent.getIntent() + ": process is bad");
11608 bringDownServiceLocked(r, true);
11609 return false;
11610 }
11611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011612 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011613 mPendingServices.add(r);
11614 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 return true;
11617 }
11618
11619 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011620 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 //r.dump(" ");
11622
11623 // Does it still need to run?
11624 if (!force && r.startRequested) {
11625 return;
11626 }
11627 if (r.connections.size() > 0) {
11628 if (!force) {
11629 // XXX should probably keep a count of the number of auto-create
11630 // connections directly in the service.
11631 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11632 while (it.hasNext()) {
11633 ConnectionRecord cr = it.next();
11634 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11635 return;
11636 }
11637 }
11638 }
11639
11640 // Report to all of the connections that the service is no longer
11641 // available.
11642 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11643 while (it.hasNext()) {
11644 ConnectionRecord c = it.next();
11645 try {
11646 // todo: shouldn't be a synchronous call!
11647 c.conn.connected(r.name, null);
11648 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011649 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011650 " to connection " + c.conn.asBinder() +
11651 " (in " + c.binding.client.processName + ")", e);
11652 }
11653 }
11654 }
11655
11656 // Tell the service that it has been unbound.
11657 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11658 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11659 while (it.hasNext()) {
11660 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011661 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011662 + ": hasBound=" + ibr.hasBound);
11663 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11664 try {
11665 bumpServiceExecutingLocked(r);
11666 updateOomAdjLocked(r.app);
11667 ibr.hasBound = false;
11668 r.app.thread.scheduleUnbindService(r,
11669 ibr.intent.getIntent());
11670 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011671 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011672 + r.shortName, e);
11673 serviceDoneExecutingLocked(r, true);
11674 }
11675 }
11676 }
11677 }
11678
Joe Onorato8a9b2202010-02-26 18:56:32 -080011679 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011680 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011681 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011682 System.identityHashCode(r), r.shortName,
11683 (r.app != null) ? r.app.pid : -1);
11684
11685 mServices.remove(r.name);
11686 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011687 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011688 r.totalRestartCount = 0;
11689 unscheduleServiceRestartLocked(r);
11690
11691 // Also make sure it is not on the pending list.
11692 int N = mPendingServices.size();
11693 for (int i=0; i<N; i++) {
11694 if (mPendingServices.get(i) == r) {
11695 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011696 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011697 TAG, "Removed pending service: " + r.shortName);
11698 i--;
11699 N--;
11700 }
11701 }
11702
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011703 r.cancelNotification();
11704 r.isForeground = false;
11705 r.foregroundId = 0;
11706 r.foregroundNoti = null;
11707
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011708 // Clear start entries.
11709 r.deliveredStarts.clear();
11710 r.pendingStarts.clear();
11711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011712 if (r.app != null) {
11713 synchronized (r.stats.getBatteryStats()) {
11714 r.stats.stopLaunchedLocked();
11715 }
11716 r.app.services.remove(r);
11717 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011718 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011719 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011720 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011721 bumpServiceExecutingLocked(r);
11722 mStoppingServices.add(r);
11723 updateOomAdjLocked(r.app);
11724 r.app.thread.scheduleStopService(r);
11725 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011726 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011727 + r.shortName, e);
11728 serviceDoneExecutingLocked(r, true);
11729 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011730 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011732 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011733 TAG, "Removed service that has no process: " + r.shortName);
11734 }
11735 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011736 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011737 TAG, "Removed service that is not running: " + r.shortName);
11738 }
11739 }
11740
11741 ComponentName startServiceLocked(IApplicationThread caller,
11742 Intent service, String resolvedType,
11743 int callingPid, int callingUid) {
11744 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011745 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011746 + " type=" + resolvedType + " args=" + service.getExtras());
11747
11748 if (caller != null) {
11749 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11750 if (callerApp == null) {
11751 throw new SecurityException(
11752 "Unable to find app for caller " + caller
11753 + " (pid=" + Binder.getCallingPid()
11754 + ") when starting service " + service);
11755 }
11756 }
11757
11758 ServiceLookupResult res =
11759 retrieveServiceLocked(service, resolvedType,
11760 callingPid, callingUid);
11761 if (res == null) {
11762 return null;
11763 }
11764 if (res.record == null) {
11765 return new ComponentName("!", res.permission != null
11766 ? res.permission : "private to package");
11767 }
11768 ServiceRecord r = res.record;
11769 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011770 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 + r.shortName);
11772 }
11773 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011774 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011775 r.lastStartId++;
11776 if (r.lastStartId < 1) {
11777 r.lastStartId = 1;
11778 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011779 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011780 r.lastActivity = SystemClock.uptimeMillis();
11781 synchronized (r.stats.getBatteryStats()) {
11782 r.stats.startRunningLocked();
11783 }
11784 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11785 return new ComponentName("!", "Service process is bad");
11786 }
11787 return r.name;
11788 }
11789 }
11790
11791 public ComponentName startService(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) {
11799 final int callingPid = Binder.getCallingPid();
11800 final int callingUid = Binder.getCallingUid();
11801 final long origId = Binder.clearCallingIdentity();
11802 ComponentName res = startServiceLocked(caller, service,
11803 resolvedType, callingPid, callingUid);
11804 Binder.restoreCallingIdentity(origId);
11805 return res;
11806 }
11807 }
11808
11809 ComponentName startServiceInPackage(int uid,
11810 Intent service, String resolvedType) {
11811 synchronized(this) {
11812 final long origId = Binder.clearCallingIdentity();
11813 ComponentName res = startServiceLocked(null, service,
11814 resolvedType, -1, uid);
11815 Binder.restoreCallingIdentity(origId);
11816 return res;
11817 }
11818 }
11819
11820 public int stopService(IApplicationThread caller, Intent service,
11821 String resolvedType) {
11822 // Refuse possible leaked file descriptors
11823 if (service != null && service.hasFileDescriptors() == true) {
11824 throw new IllegalArgumentException("File descriptors passed in Intent");
11825 }
11826
11827 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011828 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011829 + " type=" + resolvedType);
11830
11831 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11832 if (caller != null && callerApp == null) {
11833 throw new SecurityException(
11834 "Unable to find app for caller " + caller
11835 + " (pid=" + Binder.getCallingPid()
11836 + ") when stopping service " + service);
11837 }
11838
11839 // If this service is active, make sure it is stopped.
11840 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11841 if (r != null) {
11842 if (r.record != null) {
11843 synchronized (r.record.stats.getBatteryStats()) {
11844 r.record.stats.stopRunningLocked();
11845 }
11846 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011847 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011848 final long origId = Binder.clearCallingIdentity();
11849 bringDownServiceLocked(r.record, false);
11850 Binder.restoreCallingIdentity(origId);
11851 return 1;
11852 }
11853 return -1;
11854 }
11855 }
11856
11857 return 0;
11858 }
11859
11860 public IBinder peekService(Intent service, String resolvedType) {
11861 // Refuse possible leaked file descriptors
11862 if (service != null && service.hasFileDescriptors() == true) {
11863 throw new IllegalArgumentException("File descriptors passed in Intent");
11864 }
11865
11866 IBinder ret = null;
11867
11868 synchronized(this) {
11869 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11870
11871 if (r != null) {
11872 // r.record is null if findServiceLocked() failed the caller permission check
11873 if (r.record == null) {
11874 throw new SecurityException(
11875 "Permission Denial: Accessing service " + r.record.name
11876 + " from pid=" + Binder.getCallingPid()
11877 + ", uid=" + Binder.getCallingUid()
11878 + " requires " + r.permission);
11879 }
11880 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11881 if (ib != null) {
11882 ret = ib.binder;
11883 }
11884 }
11885 }
11886
11887 return ret;
11888 }
11889
11890 public boolean stopServiceToken(ComponentName className, IBinder token,
11891 int startId) {
11892 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011893 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011894 + " " + token + " startId=" + startId);
11895 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011896 if (r != null) {
11897 if (startId >= 0) {
11898 // Asked to only stop if done with all work. Note that
11899 // to avoid leaks, we will take this as dropping all
11900 // start items up to and including this one.
11901 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11902 if (si != null) {
11903 while (r.deliveredStarts.size() > 0) {
11904 if (r.deliveredStarts.remove(0) == si) {
11905 break;
11906 }
11907 }
11908 }
11909
11910 if (r.lastStartId != startId) {
11911 return false;
11912 }
11913
11914 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011915 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011916 + " is last, but have " + r.deliveredStarts.size()
11917 + " remaining args");
11918 }
11919 }
11920
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011921 synchronized (r.stats.getBatteryStats()) {
11922 r.stats.stopRunningLocked();
11923 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011924 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011925 }
11926 final long origId = Binder.clearCallingIdentity();
11927 bringDownServiceLocked(r, false);
11928 Binder.restoreCallingIdentity(origId);
11929 return true;
11930 }
11931 }
11932 return false;
11933 }
11934
11935 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011936 int id, Notification notification, boolean removeNotification) {
11937 final long origId = Binder.clearCallingIdentity();
11938 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011939 synchronized(this) {
11940 ServiceRecord r = findServiceLocked(className, token);
11941 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011942 if (id != 0) {
11943 if (notification == null) {
11944 throw new IllegalArgumentException("null notification");
11945 }
11946 if (r.foregroundId != id) {
11947 r.cancelNotification();
11948 r.foregroundId = id;
11949 }
11950 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11951 r.foregroundNoti = notification;
11952 r.isForeground = true;
11953 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011954 if (r.app != null) {
11955 updateServiceForegroundLocked(r.app, true);
11956 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011957 } else {
11958 if (r.isForeground) {
11959 r.isForeground = false;
11960 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011961 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011962 updateServiceForegroundLocked(r.app, true);
11963 }
11964 }
11965 if (removeNotification) {
11966 r.cancelNotification();
11967 r.foregroundId = 0;
11968 r.foregroundNoti = null;
11969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011970 }
11971 }
11972 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011973 } finally {
11974 Binder.restoreCallingIdentity(origId);
11975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011976 }
11977
11978 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11979 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070011980 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011981 if (sr.isForeground) {
11982 anyForeground = true;
11983 break;
11984 }
11985 }
11986 if (anyForeground != proc.foregroundServices) {
11987 proc.foregroundServices = anyForeground;
11988 if (oomAdj) {
11989 updateOomAdjLocked();
11990 }
11991 }
11992 }
11993
11994 public int bindService(IApplicationThread caller, IBinder token,
11995 Intent service, String resolvedType,
11996 IServiceConnection connection, int flags) {
11997 // Refuse possible leaked file descriptors
11998 if (service != null && service.hasFileDescriptors() == true) {
11999 throw new IllegalArgumentException("File descriptors passed in Intent");
12000 }
12001
12002 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012003 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012004 + " type=" + resolvedType + " conn=" + connection.asBinder()
12005 + " flags=0x" + Integer.toHexString(flags));
12006 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12007 if (callerApp == null) {
12008 throw new SecurityException(
12009 "Unable to find app for caller " + caller
12010 + " (pid=" + Binder.getCallingPid()
12011 + ") when binding service " + service);
12012 }
12013
12014 HistoryRecord activity = null;
12015 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070012016 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012018 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012019 return 0;
12020 }
12021 activity = (HistoryRecord)mHistory.get(aindex);
12022 }
12023
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012024 int clientLabel = 0;
12025 PendingIntent clientIntent = null;
12026
12027 if (callerApp.info.uid == Process.SYSTEM_UID) {
12028 // Hacky kind of thing -- allow system stuff to tell us
12029 // what they are, so we can report this elsewhere for
12030 // others to know why certain services are running.
12031 try {
12032 clientIntent = (PendingIntent)service.getParcelableExtra(
12033 Intent.EXTRA_CLIENT_INTENT);
12034 } catch (RuntimeException e) {
12035 }
12036 if (clientIntent != null) {
12037 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
12038 if (clientLabel != 0) {
12039 // There are no useful extras in the intent, trash them.
12040 // System code calling with this stuff just needs to know
12041 // this will happen.
12042 service = service.cloneFilter();
12043 }
12044 }
12045 }
12046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012047 ServiceLookupResult res =
12048 retrieveServiceLocked(service, resolvedType,
12049 Binder.getCallingPid(), Binder.getCallingUid());
12050 if (res == null) {
12051 return 0;
12052 }
12053 if (res.record == null) {
12054 return -1;
12055 }
12056 ServiceRecord s = res.record;
12057
12058 final long origId = Binder.clearCallingIdentity();
12059
12060 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012061 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012062 + s.shortName);
12063 }
12064
12065 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
12066 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012067 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012068
12069 IBinder binder = connection.asBinder();
12070 s.connections.put(binder, c);
12071 b.connections.add(c);
12072 if (activity != null) {
12073 if (activity.connections == null) {
12074 activity.connections = new HashSet<ConnectionRecord>();
12075 }
12076 activity.connections.add(c);
12077 }
12078 b.client.connections.add(c);
12079 mServiceConnections.put(binder, c);
12080
12081 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
12082 s.lastActivity = SystemClock.uptimeMillis();
12083 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
12084 return 0;
12085 }
12086 }
12087
12088 if (s.app != null) {
12089 // This could have made the service more important.
12090 updateOomAdjLocked(s.app);
12091 }
12092
Joe Onorato8a9b2202010-02-26 18:56:32 -080012093 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012094 + ": received=" + b.intent.received
12095 + " apps=" + b.intent.apps.size()
12096 + " doRebind=" + b.intent.doRebind);
12097
12098 if (s.app != null && b.intent.received) {
12099 // Service is already running, so we can immediately
12100 // publish the connection.
12101 try {
12102 c.conn.connected(s.name, b.intent.binder);
12103 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012104 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012105 + " to connection " + c.conn.asBinder()
12106 + " (in " + c.binding.client.processName + ")", e);
12107 }
12108
12109 // If this is the first app connected back to this binding,
12110 // and the service had previously asked to be told when
12111 // rebound, then do so.
12112 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
12113 requestServiceBindingLocked(s, b.intent, true);
12114 }
12115 } else if (!b.intent.requested) {
12116 requestServiceBindingLocked(s, b.intent, false);
12117 }
12118
12119 Binder.restoreCallingIdentity(origId);
12120 }
12121
12122 return 1;
12123 }
12124
12125 private void removeConnectionLocked(
12126 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
12127 IBinder binder = c.conn.asBinder();
12128 AppBindRecord b = c.binding;
12129 ServiceRecord s = b.service;
12130 s.connections.remove(binder);
12131 b.connections.remove(c);
12132 if (c.activity != null && c.activity != skipAct) {
12133 if (c.activity.connections != null) {
12134 c.activity.connections.remove(c);
12135 }
12136 }
12137 if (b.client != skipApp) {
12138 b.client.connections.remove(c);
12139 }
12140 mServiceConnections.remove(binder);
12141
12142 if (b.connections.size() == 0) {
12143 b.intent.apps.remove(b.client);
12144 }
12145
Joe Onorato8a9b2202010-02-26 18:56:32 -080012146 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012147 + ": shouldUnbind=" + b.intent.hasBound);
12148 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
12149 && b.intent.hasBound) {
12150 try {
12151 bumpServiceExecutingLocked(s);
12152 updateOomAdjLocked(s.app);
12153 b.intent.hasBound = false;
12154 // Assume the client doesn't want to know about a rebind;
12155 // we will deal with that later if it asks for one.
12156 b.intent.doRebind = false;
12157 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
12158 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012159 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012160 serviceDoneExecutingLocked(s, true);
12161 }
12162 }
12163
12164 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
12165 bringDownServiceLocked(s, false);
12166 }
12167 }
12168
12169 public boolean unbindService(IServiceConnection connection) {
12170 synchronized (this) {
12171 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012172 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012173 ConnectionRecord r = mServiceConnections.get(binder);
12174 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012175 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012176 + connection.asBinder());
12177 return false;
12178 }
12179
12180 final long origId = Binder.clearCallingIdentity();
12181
12182 removeConnectionLocked(r, null, null);
12183
12184 if (r.binding.service.app != null) {
12185 // This could have made the service less important.
12186 updateOomAdjLocked(r.binding.service.app);
12187 }
12188
12189 Binder.restoreCallingIdentity(origId);
12190 }
12191
12192 return true;
12193 }
12194
12195 public void publishService(IBinder token, Intent intent, IBinder service) {
12196 // Refuse possible leaked file descriptors
12197 if (intent != null && intent.hasFileDescriptors() == true) {
12198 throw new IllegalArgumentException("File descriptors passed in Intent");
12199 }
12200
12201 synchronized(this) {
12202 if (!(token instanceof ServiceRecord)) {
12203 throw new IllegalArgumentException("Invalid service token");
12204 }
12205 ServiceRecord r = (ServiceRecord)token;
12206
12207 final long origId = Binder.clearCallingIdentity();
12208
Joe Onorato8a9b2202010-02-26 18:56:32 -080012209 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012210 + " " + intent + ": " + service);
12211 if (r != null) {
12212 Intent.FilterComparison filter
12213 = new Intent.FilterComparison(intent);
12214 IntentBindRecord b = r.bindings.get(filter);
12215 if (b != null && !b.received) {
12216 b.binder = service;
12217 b.requested = true;
12218 b.received = true;
12219 if (r.connections.size() > 0) {
12220 Iterator<ConnectionRecord> it
12221 = r.connections.values().iterator();
12222 while (it.hasNext()) {
12223 ConnectionRecord c = it.next();
12224 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012225 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012227 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012228 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012229 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012230 TAG, "Published intent: " + intent);
12231 continue;
12232 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012233 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012234 try {
12235 c.conn.connected(r.name, service);
12236 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012237 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012238 " to connection " + c.conn.asBinder() +
12239 " (in " + c.binding.client.processName + ")", e);
12240 }
12241 }
12242 }
12243 }
12244
12245 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12246
12247 Binder.restoreCallingIdentity(origId);
12248 }
12249 }
12250 }
12251
12252 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
12253 // Refuse possible leaked file descriptors
12254 if (intent != null && intent.hasFileDescriptors() == true) {
12255 throw new IllegalArgumentException("File descriptors passed in Intent");
12256 }
12257
12258 synchronized(this) {
12259 if (!(token instanceof ServiceRecord)) {
12260 throw new IllegalArgumentException("Invalid service token");
12261 }
12262 ServiceRecord r = (ServiceRecord)token;
12263
12264 final long origId = Binder.clearCallingIdentity();
12265
12266 if (r != null) {
12267 Intent.FilterComparison filter
12268 = new Intent.FilterComparison(intent);
12269 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012270 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012271 + " at " + b + ": apps="
12272 + (b != null ? b.apps.size() : 0));
12273 if (b != null) {
12274 if (b.apps.size() > 0) {
12275 // Applications have already bound since the last
12276 // unbind, so just rebind right here.
12277 requestServiceBindingLocked(r, b, true);
12278 } else {
12279 // Note to tell the service the next time there is
12280 // a new client.
12281 b.doRebind = true;
12282 }
12283 }
12284
12285 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12286
12287 Binder.restoreCallingIdentity(origId);
12288 }
12289 }
12290 }
12291
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012292 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012293 synchronized(this) {
12294 if (!(token instanceof ServiceRecord)) {
12295 throw new IllegalArgumentException("Invalid service token");
12296 }
12297 ServiceRecord r = (ServiceRecord)token;
12298 boolean inStopping = mStoppingServices.contains(token);
12299 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012300 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012301 + ": nesting=" + r.executeNesting
12302 + ", inStopping=" + inStopping);
12303 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012304 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012305 + " with incorrect token: given " + token
12306 + ", expected " + r);
12307 return;
12308 }
12309
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012310 if (type == 1) {
12311 // This is a call from a service start... take care of
12312 // book-keeping.
12313 r.callStart = true;
12314 switch (res) {
12315 case Service.START_STICKY_COMPATIBILITY:
12316 case Service.START_STICKY: {
12317 // We are done with the associated start arguments.
12318 r.findDeliveredStart(startId, true);
12319 // Don't stop if killed.
12320 r.stopIfKilled = false;
12321 break;
12322 }
12323 case Service.START_NOT_STICKY: {
12324 // We are done with the associated start arguments.
12325 r.findDeliveredStart(startId, true);
12326 if (r.lastStartId == startId) {
12327 // There is no more work, and this service
12328 // doesn't want to hang around if killed.
12329 r.stopIfKilled = true;
12330 }
12331 break;
12332 }
12333 case Service.START_REDELIVER_INTENT: {
12334 // We'll keep this item until they explicitly
12335 // call stop for it, but keep track of the fact
12336 // that it was delivered.
12337 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12338 if (si != null) {
12339 si.deliveryCount = 0;
12340 si.doneExecutingCount++;
12341 // Don't stop if killed.
12342 r.stopIfKilled = true;
12343 }
12344 break;
12345 }
12346 default:
12347 throw new IllegalArgumentException(
12348 "Unknown service start result: " + res);
12349 }
12350 if (res == Service.START_STICKY_COMPATIBILITY) {
12351 r.callStart = false;
12352 }
12353 }
12354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012355 final long origId = Binder.clearCallingIdentity();
12356 serviceDoneExecutingLocked(r, inStopping);
12357 Binder.restoreCallingIdentity(origId);
12358 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012359 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012360 + " with token " + token);
12361 }
12362 }
12363 }
12364
12365 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
12366 r.executeNesting--;
12367 if (r.executeNesting <= 0 && r.app != null) {
12368 r.app.executingServices.remove(r);
12369 if (r.app.executingServices.size() == 0) {
12370 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
12371 }
12372 if (inStopping) {
12373 mStoppingServices.remove(r);
12374 }
12375 updateOomAdjLocked(r.app);
12376 }
12377 }
12378
12379 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012380 String anrMessage = null;
12381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012382 synchronized(this) {
12383 if (proc.executingServices.size() == 0 || proc.thread == null) {
12384 return;
12385 }
12386 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12387 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12388 ServiceRecord timeout = null;
12389 long nextTime = 0;
12390 while (it.hasNext()) {
12391 ServiceRecord sr = it.next();
12392 if (sr.executingStart < maxTime) {
12393 timeout = sr;
12394 break;
12395 }
12396 if (sr.executingStart > nextTime) {
12397 nextTime = sr.executingStart;
12398 }
12399 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012400 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012401 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012402 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012403 } else {
12404 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12405 msg.obj = proc;
12406 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12407 }
12408 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012409
12410 if (anrMessage != null) {
12411 appNotResponding(proc, null, null, anrMessage);
12412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012413 }
12414
12415 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012416 // BACKUP AND RESTORE
12417 // =========================================================
12418
12419 // Cause the target app to be launched if necessary and its backup agent
12420 // instantiated. The backup agent will invoke backupAgentCreated() on the
12421 // activity manager to announce its creation.
12422 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012423 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012424 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12425
12426 synchronized(this) {
12427 // !!! TODO: currently no check here that we're already bound
12428 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12429 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12430 synchronized (stats) {
12431 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12432 }
12433
12434 BackupRecord r = new BackupRecord(ss, app, backupMode);
12435 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12436 // startProcessLocked() returns existing proc's record if it's already running
12437 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012438 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012439 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012440 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012441 return false;
12442 }
12443
12444 r.app = proc;
12445 mBackupTarget = r;
12446 mBackupAppName = app.packageName;
12447
Christopher Tate6fa95972009-06-05 18:43:55 -070012448 // Try not to kill the process during backup
12449 updateOomAdjLocked(proc);
12450
Christopher Tate181fafa2009-05-14 11:12:14 -070012451 // If the process is already attached, schedule the creation of the backup agent now.
12452 // If it is not yet live, this will be done when it attaches to the framework.
12453 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012454 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012455 try {
12456 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12457 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012458 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012459 }
12460 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012461 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012462 }
12463 // Invariants: at this point, the target app process exists and the application
12464 // is either already running or in the process of coming up. mBackupTarget and
12465 // mBackupAppName describe the app, so that when it binds back to the AM we
12466 // know that it's scheduled for a backup-agent operation.
12467 }
12468
12469 return true;
12470 }
12471
12472 // A backup agent has just come up
12473 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012474 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012475 + " = " + agent);
12476
12477 synchronized(this) {
12478 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012479 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012480 return;
12481 }
12482
Christopher Tate043dadc2009-06-02 16:11:00 -070012483 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012484 try {
12485 IBackupManager bm = IBackupManager.Stub.asInterface(
12486 ServiceManager.getService(Context.BACKUP_SERVICE));
12487 bm.agentConnected(agentPackageName, agent);
12488 } catch (RemoteException e) {
12489 // can't happen; the backup manager service is local
12490 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012491 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012492 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012493 } finally {
12494 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012495 }
12496 }
12497 }
12498
12499 // done with this agent
12500 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012501 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012502 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012503 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012504 return;
12505 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012506
12507 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012508 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012509 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012510 return;
12511 }
12512
Christopher Tate181fafa2009-05-14 11:12:14 -070012513 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012514 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012515 return;
12516 }
12517
Christopher Tate6fa95972009-06-05 18:43:55 -070012518 ProcessRecord proc = mBackupTarget.app;
12519 mBackupTarget = null;
12520 mBackupAppName = null;
12521
12522 // Not backing this app up any more; reset its OOM adjustment
12523 updateOomAdjLocked(proc);
12524
Christopher Tatec7b31e32009-06-10 15:49:30 -070012525 // If the app crashed during backup, 'thread' will be null here
12526 if (proc.thread != null) {
12527 try {
12528 proc.thread.scheduleDestroyBackupAgent(appInfo);
12529 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012530 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012531 e.printStackTrace();
12532 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012533 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012534 }
12535 }
12536 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012537 // BROADCASTS
12538 // =========================================================
12539
Josh Bartel7f208742010-02-25 11:01:44 -060012540 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012541 List cur) {
12542 final ContentResolver resolver = mContext.getContentResolver();
12543 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12544 if (list == null) {
12545 return cur;
12546 }
12547 int N = list.size();
12548 for (int i=0; i<N; i++) {
12549 Intent intent = list.get(i);
12550 if (filter.match(resolver, intent, true, TAG) >= 0) {
12551 if (cur == null) {
12552 cur = new ArrayList<Intent>();
12553 }
12554 cur.add(intent);
12555 }
12556 }
12557 return cur;
12558 }
12559
12560 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012561 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012562 + mBroadcastsScheduled);
12563
12564 if (mBroadcastsScheduled) {
12565 return;
12566 }
12567 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12568 mBroadcastsScheduled = true;
12569 }
12570
12571 public Intent registerReceiver(IApplicationThread caller,
12572 IIntentReceiver receiver, IntentFilter filter, String permission) {
12573 synchronized(this) {
12574 ProcessRecord callerApp = null;
12575 if (caller != null) {
12576 callerApp = getRecordForAppLocked(caller);
12577 if (callerApp == null) {
12578 throw new SecurityException(
12579 "Unable to find app for caller " + caller
12580 + " (pid=" + Binder.getCallingPid()
12581 + ") when registering receiver " + receiver);
12582 }
12583 }
12584
12585 List allSticky = null;
12586
12587 // Look for any matching sticky broadcasts...
12588 Iterator actions = filter.actionsIterator();
12589 if (actions != null) {
12590 while (actions.hasNext()) {
12591 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012592 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012593 }
12594 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012595 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012596 }
12597
12598 // The first sticky in the list is returned directly back to
12599 // the client.
12600 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12601
Joe Onorato8a9b2202010-02-26 18:56:32 -080012602 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012603 + ": " + sticky);
12604
12605 if (receiver == null) {
12606 return sticky;
12607 }
12608
12609 ReceiverList rl
12610 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12611 if (rl == null) {
12612 rl = new ReceiverList(this, callerApp,
12613 Binder.getCallingPid(),
12614 Binder.getCallingUid(), receiver);
12615 if (rl.app != null) {
12616 rl.app.receivers.add(rl);
12617 } else {
12618 try {
12619 receiver.asBinder().linkToDeath(rl, 0);
12620 } catch (RemoteException e) {
12621 return sticky;
12622 }
12623 rl.linkedToDeath = true;
12624 }
12625 mRegisteredReceivers.put(receiver.asBinder(), rl);
12626 }
12627 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12628 rl.add(bf);
12629 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012630 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012631 }
12632 mReceiverResolver.addFilter(bf);
12633
12634 // Enqueue broadcasts for all existing stickies that match
12635 // this filter.
12636 if (allSticky != null) {
12637 ArrayList receivers = new ArrayList();
12638 receivers.add(bf);
12639
12640 int N = allSticky.size();
12641 for (int i=0; i<N; i++) {
12642 Intent intent = (Intent)allSticky.get(i);
12643 BroadcastRecord r = new BroadcastRecord(intent, null,
12644 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012645 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012646 if (mParallelBroadcasts.size() == 0) {
12647 scheduleBroadcastsLocked();
12648 }
12649 mParallelBroadcasts.add(r);
12650 }
12651 }
12652
12653 return sticky;
12654 }
12655 }
12656
12657 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012658 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012659
12660 boolean doNext = false;
12661
12662 synchronized(this) {
12663 ReceiverList rl
12664 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12665 if (rl != null) {
12666 if (rl.curBroadcast != null) {
12667 BroadcastRecord r = rl.curBroadcast;
12668 doNext = finishReceiverLocked(
12669 receiver.asBinder(), r.resultCode, r.resultData,
12670 r.resultExtras, r.resultAbort, true);
12671 }
12672
12673 if (rl.app != null) {
12674 rl.app.receivers.remove(rl);
12675 }
12676 removeReceiverLocked(rl);
12677 if (rl.linkedToDeath) {
12678 rl.linkedToDeath = false;
12679 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12680 }
12681 }
12682 }
12683
12684 if (!doNext) {
12685 return;
12686 }
12687
12688 final long origId = Binder.clearCallingIdentity();
12689 processNextBroadcast(false);
12690 trimApplications();
12691 Binder.restoreCallingIdentity(origId);
12692 }
12693
12694 void removeReceiverLocked(ReceiverList rl) {
12695 mRegisteredReceivers.remove(rl.receiver.asBinder());
12696 int N = rl.size();
12697 for (int i=0; i<N; i++) {
12698 mReceiverResolver.removeFilter(rl.get(i));
12699 }
12700 }
12701
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012702 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12703 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12704 ProcessRecord r = mLruProcesses.get(i);
12705 if (r.thread != null) {
12706 try {
12707 r.thread.dispatchPackageBroadcast(cmd, packages);
12708 } catch (RemoteException ex) {
12709 }
12710 }
12711 }
12712 }
12713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012714 private final int broadcastIntentLocked(ProcessRecord callerApp,
12715 String callerPackage, Intent intent, String resolvedType,
12716 IIntentReceiver resultTo, int resultCode, String resultData,
12717 Bundle map, String requiredPermission,
12718 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12719 intent = new Intent(intent);
12720
Joe Onorato8a9b2202010-02-26 18:56:32 -080012721 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012722 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12723 + " ordered=" + ordered);
12724 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012725 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012726 }
12727
12728 // Handle special intents: if this broadcast is from the package
12729 // manager about a package being removed, we need to remove all of
12730 // its activities from the history stack.
12731 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12732 intent.getAction());
12733 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12734 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012735 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012736 || uidRemoved) {
12737 if (checkComponentPermission(
12738 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12739 callingPid, callingUid, -1)
12740 == PackageManager.PERMISSION_GRANTED) {
12741 if (uidRemoved) {
12742 final Bundle intentExtras = intent.getExtras();
12743 final int uid = intentExtras != null
12744 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12745 if (uid >= 0) {
12746 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12747 synchronized (bs) {
12748 bs.removeUidStatsLocked(uid);
12749 }
12750 }
12751 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012752 // If resources are unvailble just force stop all
12753 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012754 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012755 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12756 if (list != null && (list.length > 0)) {
12757 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012758 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012759 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012760 sendPackageBroadcastLocked(
12761 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012762 }
12763 } else {
12764 Uri data = intent.getData();
12765 String ssp;
12766 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12767 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12768 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012769 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012770 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012771 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
12772 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12773 new String[] {ssp});
12774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012775 }
12776 }
12777 }
12778 } else {
12779 String msg = "Permission Denial: " + intent.getAction()
12780 + " broadcast from " + callerPackage + " (pid=" + callingPid
12781 + ", uid=" + callingUid + ")"
12782 + " requires "
12783 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012784 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012785 throw new SecurityException(msg);
12786 }
12787 }
12788
12789 /*
12790 * If this is the time zone changed action, queue up a message that will reset the timezone
12791 * of all currently running processes. This message will get queued up before the broadcast
12792 * happens.
12793 */
12794 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12795 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12796 }
12797
Dianne Hackborn854060af2009-07-09 18:14:31 -070012798 /*
12799 * Prevent non-system code (defined here to be non-persistent
12800 * processes) from sending protected broadcasts.
12801 */
12802 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12803 || callingUid == Process.SHELL_UID || callingUid == 0) {
12804 // Always okay.
12805 } else if (callerApp == null || !callerApp.persistent) {
12806 try {
12807 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12808 intent.getAction())) {
12809 String msg = "Permission Denial: not allowed to send broadcast "
12810 + intent.getAction() + " from pid="
12811 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012812 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012813 throw new SecurityException(msg);
12814 }
12815 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012816 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012817 return BROADCAST_SUCCESS;
12818 }
12819 }
12820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012821 // Add to the sticky list if requested.
12822 if (sticky) {
12823 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12824 callingPid, callingUid)
12825 != PackageManager.PERMISSION_GRANTED) {
12826 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12827 + callingPid + ", uid=" + callingUid
12828 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012829 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012830 throw new SecurityException(msg);
12831 }
12832 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012833 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012834 + " and enforce permission " + requiredPermission);
12835 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12836 }
12837 if (intent.getComponent() != null) {
12838 throw new SecurityException(
12839 "Sticky broadcasts can't target a specific component");
12840 }
12841 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12842 if (list == null) {
12843 list = new ArrayList<Intent>();
12844 mStickyBroadcasts.put(intent.getAction(), list);
12845 }
12846 int N = list.size();
12847 int i;
12848 for (i=0; i<N; i++) {
12849 if (intent.filterEquals(list.get(i))) {
12850 // This sticky already exists, replace it.
12851 list.set(i, new Intent(intent));
12852 break;
12853 }
12854 }
12855 if (i >= N) {
12856 list.add(new Intent(intent));
12857 }
12858 }
12859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012860 // Figure out who all will receive this broadcast.
12861 List receivers = null;
12862 List<BroadcastFilter> registeredReceivers = null;
12863 try {
12864 if (intent.getComponent() != null) {
12865 // Broadcast is going to one specific receiver class...
12866 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012867 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012868 if (ai != null) {
12869 receivers = new ArrayList();
12870 ResolveInfo ri = new ResolveInfo();
12871 ri.activityInfo = ai;
12872 receivers.add(ri);
12873 }
12874 } else {
12875 // Need to resolve the intent to interested receivers...
12876 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12877 == 0) {
12878 receivers =
12879 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012880 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012881 }
Mihai Preda074edef2009-05-18 17:13:31 +020012882 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012883 }
12884 } catch (RemoteException ex) {
12885 // pm is in same process, this will never happen.
12886 }
12887
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012888 final boolean replacePending =
12889 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12890
Joe Onorato8a9b2202010-02-26 18:56:32 -080012891 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012892 + " replacePending=" + replacePending);
12893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012894 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12895 if (!ordered && NR > 0) {
12896 // If we are not serializing this broadcast, then send the
12897 // registered receivers separately so they don't wait for the
12898 // components to be launched.
12899 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12900 callerPackage, callingPid, callingUid, requiredPermission,
12901 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012902 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012903 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012904 TAG, "Enqueueing parallel broadcast " + r
12905 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012906 boolean replaced = false;
12907 if (replacePending) {
12908 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12909 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012910 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012911 "***** DROPPING PARALLEL: " + intent);
12912 mParallelBroadcasts.set(i, r);
12913 replaced = true;
12914 break;
12915 }
12916 }
12917 }
12918 if (!replaced) {
12919 mParallelBroadcasts.add(r);
12920 scheduleBroadcastsLocked();
12921 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012922 registeredReceivers = null;
12923 NR = 0;
12924 }
12925
12926 // Merge into one list.
12927 int ir = 0;
12928 if (receivers != null) {
12929 // A special case for PACKAGE_ADDED: do not allow the package
12930 // being added to see this broadcast. This prevents them from
12931 // using this as a back door to get run as soon as they are
12932 // installed. Maybe in the future we want to have a special install
12933 // broadcast or such for apps, but we'd like to deliberately make
12934 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012935 String skipPackages[] = null;
12936 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12937 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12938 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12939 Uri data = intent.getData();
12940 if (data != null) {
12941 String pkgName = data.getSchemeSpecificPart();
12942 if (pkgName != null) {
12943 skipPackages = new String[] { pkgName };
12944 }
12945 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012946 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012947 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012948 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012949 if (skipPackages != null && (skipPackages.length > 0)) {
12950 for (String skipPackage : skipPackages) {
12951 if (skipPackage != null) {
12952 int NT = receivers.size();
12953 for (int it=0; it<NT; it++) {
12954 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12955 if (curt.activityInfo.packageName.equals(skipPackage)) {
12956 receivers.remove(it);
12957 it--;
12958 NT--;
12959 }
12960 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012961 }
12962 }
12963 }
12964
12965 int NT = receivers != null ? receivers.size() : 0;
12966 int it = 0;
12967 ResolveInfo curt = null;
12968 BroadcastFilter curr = null;
12969 while (it < NT && ir < NR) {
12970 if (curt == null) {
12971 curt = (ResolveInfo)receivers.get(it);
12972 }
12973 if (curr == null) {
12974 curr = registeredReceivers.get(ir);
12975 }
12976 if (curr.getPriority() >= curt.priority) {
12977 // Insert this broadcast record into the final list.
12978 receivers.add(it, curr);
12979 ir++;
12980 curr = null;
12981 it++;
12982 NT++;
12983 } else {
12984 // Skip to the next ResolveInfo in the final list.
12985 it++;
12986 curt = null;
12987 }
12988 }
12989 }
12990 while (ir < NR) {
12991 if (receivers == null) {
12992 receivers = new ArrayList();
12993 }
12994 receivers.add(registeredReceivers.get(ir));
12995 ir++;
12996 }
12997
12998 if ((receivers != null && receivers.size() > 0)
12999 || resultTo != null) {
13000 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
13001 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013002 receivers, resultTo, resultCode, resultData, map, ordered,
13003 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013004 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013005 TAG, "Enqueueing ordered broadcast " + r
13006 + ": prev had " + mOrderedBroadcasts.size());
13007 if (DEBUG_BROADCAST) {
13008 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013009 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013010 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013011 boolean replaced = false;
13012 if (replacePending) {
13013 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
13014 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013015 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013016 "***** DROPPING ORDERED: " + intent);
13017 mOrderedBroadcasts.set(i, r);
13018 replaced = true;
13019 break;
13020 }
13021 }
13022 }
13023 if (!replaced) {
13024 mOrderedBroadcasts.add(r);
13025 scheduleBroadcastsLocked();
13026 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013027 }
13028
13029 return BROADCAST_SUCCESS;
13030 }
13031
13032 public final int broadcastIntent(IApplicationThread caller,
13033 Intent intent, String resolvedType, IIntentReceiver resultTo,
13034 int resultCode, String resultData, Bundle map,
13035 String requiredPermission, boolean serialized, boolean sticky) {
13036 // Refuse possible leaked file descriptors
13037 if (intent != null && intent.hasFileDescriptors() == true) {
13038 throw new IllegalArgumentException("File descriptors passed in Intent");
13039 }
13040
13041 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013042 int flags = intent.getFlags();
13043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013044 if (!mSystemReady) {
13045 // if the caller really truly claims to know what they're doing, go
13046 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013047 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
13048 intent = new Intent(intent);
13049 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
13050 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080013051 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013052 + " before boot completion");
13053 throw new IllegalStateException("Cannot broadcast before boot completed");
13054 }
13055 }
13056
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013057 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
13058 throw new IllegalArgumentException(
13059 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
13060 }
13061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013062 final ProcessRecord callerApp = getRecordForAppLocked(caller);
13063 final int callingPid = Binder.getCallingPid();
13064 final int callingUid = Binder.getCallingUid();
13065 final long origId = Binder.clearCallingIdentity();
13066 int res = broadcastIntentLocked(callerApp,
13067 callerApp != null ? callerApp.info.packageName : null,
13068 intent, resolvedType, resultTo,
13069 resultCode, resultData, map, requiredPermission, serialized,
13070 sticky, callingPid, callingUid);
13071 Binder.restoreCallingIdentity(origId);
13072 return res;
13073 }
13074 }
13075
13076 int broadcastIntentInPackage(String packageName, int uid,
13077 Intent intent, String resolvedType, IIntentReceiver resultTo,
13078 int resultCode, String resultData, Bundle map,
13079 String requiredPermission, boolean serialized, boolean sticky) {
13080 synchronized(this) {
13081 final long origId = Binder.clearCallingIdentity();
13082 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
13083 resultTo, resultCode, resultData, map, requiredPermission,
13084 serialized, sticky, -1, uid);
13085 Binder.restoreCallingIdentity(origId);
13086 return res;
13087 }
13088 }
13089
13090 public final void unbroadcastIntent(IApplicationThread caller,
13091 Intent intent) {
13092 // Refuse possible leaked file descriptors
13093 if (intent != null && intent.hasFileDescriptors() == true) {
13094 throw new IllegalArgumentException("File descriptors passed in Intent");
13095 }
13096
13097 synchronized(this) {
13098 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
13099 != PackageManager.PERMISSION_GRANTED) {
13100 String msg = "Permission Denial: unbroadcastIntent() from pid="
13101 + Binder.getCallingPid()
13102 + ", uid=" + Binder.getCallingUid()
13103 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013104 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013105 throw new SecurityException(msg);
13106 }
13107 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
13108 if (list != null) {
13109 int N = list.size();
13110 int i;
13111 for (i=0; i<N; i++) {
13112 if (intent.filterEquals(list.get(i))) {
13113 list.remove(i);
13114 break;
13115 }
13116 }
13117 }
13118 }
13119 }
13120
13121 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
13122 String resultData, Bundle resultExtras, boolean resultAbort,
13123 boolean explicit) {
13124 if (mOrderedBroadcasts.size() == 0) {
13125 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013126 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013127 }
13128 return false;
13129 }
13130 BroadcastRecord r = mOrderedBroadcasts.get(0);
13131 if (r.receiver == null) {
13132 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013133 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013134 }
13135 return false;
13136 }
13137 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013138 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013139 return false;
13140 }
13141 int state = r.state;
13142 r.state = r.IDLE;
13143 if (state == r.IDLE) {
13144 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013145 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013146 }
13147 }
13148 r.receiver = null;
13149 r.intent.setComponent(null);
13150 if (r.curApp != null) {
13151 r.curApp.curReceiver = null;
13152 }
13153 if (r.curFilter != null) {
13154 r.curFilter.receiverList.curBroadcast = null;
13155 }
13156 r.curFilter = null;
13157 r.curApp = null;
13158 r.curComponent = null;
13159 r.curReceiver = null;
13160 mPendingBroadcast = null;
13161
13162 r.resultCode = resultCode;
13163 r.resultData = resultData;
13164 r.resultExtras = resultExtras;
13165 r.resultAbort = resultAbort;
13166
13167 // We will process the next receiver right now if this is finishing
13168 // an app receiver (which is always asynchronous) or after we have
13169 // come back from calling a receiver.
13170 return state == BroadcastRecord.APP_RECEIVE
13171 || state == BroadcastRecord.CALL_DONE_RECEIVE;
13172 }
13173
13174 public void finishReceiver(IBinder who, int resultCode, String resultData,
13175 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013176 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013177
13178 // Refuse possible leaked file descriptors
13179 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
13180 throw new IllegalArgumentException("File descriptors passed in Bundle");
13181 }
13182
13183 boolean doNext;
13184
13185 final long origId = Binder.clearCallingIdentity();
13186
13187 synchronized(this) {
13188 doNext = finishReceiverLocked(
13189 who, resultCode, resultData, resultExtras, resultAbort, true);
13190 }
13191
13192 if (doNext) {
13193 processNextBroadcast(false);
13194 }
13195 trimApplications();
13196
13197 Binder.restoreCallingIdentity(origId);
13198 }
13199
13200 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
13201 if (r.nextReceiver > 0) {
13202 Object curReceiver = r.receivers.get(r.nextReceiver-1);
13203 if (curReceiver instanceof BroadcastFilter) {
13204 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080013205 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013206 System.identityHashCode(r),
13207 r.intent.getAction(),
13208 r.nextReceiver - 1,
13209 System.identityHashCode(bf));
13210 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080013211 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013212 System.identityHashCode(r),
13213 r.intent.getAction(),
13214 r.nextReceiver - 1,
13215 ((ResolveInfo)curReceiver).toString());
13216 }
13217 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013218 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013219 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013220 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013221 System.identityHashCode(r),
13222 r.intent.getAction(),
13223 r.nextReceiver,
13224 "NONE");
13225 }
13226 }
13227
13228 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013229 ProcessRecord app = null;
13230 String anrMessage = null;
13231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013232 synchronized (this) {
13233 if (mOrderedBroadcasts.size() == 0) {
13234 return;
13235 }
13236 long now = SystemClock.uptimeMillis();
13237 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013238 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013239 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013240 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013241 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013242 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013243 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013244 return;
13245 }
13246
Joe Onorato8a9b2202010-02-26 18:56:32 -080013247 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013248 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013249 r.anrCount++;
13250
13251 // Current receiver has passed its expiration date.
13252 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013253 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013254 return;
13255 }
13256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013257 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013258 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013259 logBroadcastReceiverDiscard(r);
13260 if (curReceiver instanceof BroadcastFilter) {
13261 BroadcastFilter bf = (BroadcastFilter)curReceiver;
13262 if (bf.receiverList.pid != 0
13263 && bf.receiverList.pid != MY_PID) {
13264 synchronized (this.mPidsSelfLocked) {
13265 app = this.mPidsSelfLocked.get(
13266 bf.receiverList.pid);
13267 }
13268 }
13269 } else {
13270 app = r.curApp;
13271 }
13272
13273 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013274 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013275 }
13276
13277 if (mPendingBroadcast == r) {
13278 mPendingBroadcast = null;
13279 }
13280
13281 // Move on to the next receiver.
13282 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13283 r.resultExtras, r.resultAbort, true);
13284 scheduleBroadcastsLocked();
13285 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013286
13287 if (anrMessage != null) {
13288 appNotResponding(app, null, null, anrMessage);
13289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013290 }
13291
13292 private final void processCurBroadcastLocked(BroadcastRecord r,
13293 ProcessRecord app) throws RemoteException {
13294 if (app.thread == null) {
13295 throw new RemoteException();
13296 }
13297 r.receiver = app.thread.asBinder();
13298 r.curApp = app;
13299 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013300 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013301
13302 // Tell the application to launch this receiver.
13303 r.intent.setComponent(r.curComponent);
13304
13305 boolean started = false;
13306 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013307 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013308 "Delivering to component " + r.curComponent
13309 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070013310 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013311 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
13312 r.resultCode, r.resultData, r.resultExtras, r.ordered);
13313 started = true;
13314 } finally {
13315 if (!started) {
13316 r.receiver = null;
13317 r.curApp = null;
13318 app.curReceiver = null;
13319 }
13320 }
13321
13322 }
13323
13324 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013325 Intent intent, int resultCode, String data, Bundle extras,
13326 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013327 if (app != null && app.thread != null) {
13328 // If we have an app thread, do the call through that so it is
13329 // correctly ordered with other one-way calls.
13330 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013331 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013332 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013333 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013334 }
13335 }
13336
13337 private final void deliverToRegisteredReceiver(BroadcastRecord r,
13338 BroadcastFilter filter, boolean ordered) {
13339 boolean skip = false;
13340 if (filter.requiredPermission != null) {
13341 int perm = checkComponentPermission(filter.requiredPermission,
13342 r.callingPid, r.callingUid, -1);
13343 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013344 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013345 + r.intent.toString()
13346 + " from " + r.callerPackage + " (pid="
13347 + r.callingPid + ", uid=" + r.callingUid + ")"
13348 + " requires " + filter.requiredPermission
13349 + " due to registered receiver " + filter);
13350 skip = true;
13351 }
13352 }
13353 if (r.requiredPermission != null) {
13354 int perm = checkComponentPermission(r.requiredPermission,
13355 filter.receiverList.pid, filter.receiverList.uid, -1);
13356 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013357 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013358 + r.intent.toString()
13359 + " to " + filter.receiverList.app
13360 + " (pid=" + filter.receiverList.pid
13361 + ", uid=" + filter.receiverList.uid + ")"
13362 + " requires " + r.requiredPermission
13363 + " due to sender " + r.callerPackage
13364 + " (uid " + r.callingUid + ")");
13365 skip = true;
13366 }
13367 }
13368
13369 if (!skip) {
13370 // If this is not being sent as an ordered broadcast, then we
13371 // don't want to touch the fields that keep track of the current
13372 // state of ordered broadcasts.
13373 if (ordered) {
13374 r.receiver = filter.receiverList.receiver.asBinder();
13375 r.curFilter = filter;
13376 filter.receiverList.curBroadcast = r;
13377 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013378 if (filter.receiverList.app != null) {
13379 // Bump hosting application to no longer be in background
13380 // scheduling class. Note that we can't do that if there
13381 // isn't an app... but we can only be in that case for
13382 // things that directly call the IActivityManager API, which
13383 // are already core system stuff so don't matter for this.
13384 r.curApp = filter.receiverList.app;
13385 filter.receiverList.app.curReceiver = r;
13386 updateOomAdjLocked();
13387 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013388 }
13389 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013390 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013391 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013392 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013393 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013394 }
13395 performReceive(filter.receiverList.app, filter.receiverList.receiver,
13396 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013397 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013398 if (ordered) {
13399 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13400 }
13401 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013402 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013403 if (ordered) {
13404 r.receiver = null;
13405 r.curFilter = null;
13406 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013407 if (filter.receiverList.app != null) {
13408 filter.receiverList.app.curReceiver = null;
13409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013410 }
13411 }
13412 }
13413 }
13414
Dianne Hackborn12527f92009-11-11 17:39:50 -080013415 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13416 if (r.callingUid < 0) {
13417 // This was from a registerReceiver() call; ignore it.
13418 return;
13419 }
13420 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13421 MAX_BROADCAST_HISTORY-1);
13422 r.finishTime = SystemClock.uptimeMillis();
13423 mBroadcastHistory[0] = r;
13424 }
13425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013426 private final void processNextBroadcast(boolean fromMsg) {
13427 synchronized(this) {
13428 BroadcastRecord r;
13429
Joe Onorato8a9b2202010-02-26 18:56:32 -080013430 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013431 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013432 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013433
13434 updateCpuStats();
13435
13436 if (fromMsg) {
13437 mBroadcastsScheduled = false;
13438 }
13439
13440 // First, deliver any non-serialized broadcasts right away.
13441 while (mParallelBroadcasts.size() > 0) {
13442 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013443 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013444 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013445 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013446 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013447 for (int i=0; i<N; i++) {
13448 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013449 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013450 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013451 + target + ": " + r);
13452 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13453 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013454 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013455 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013456 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013457 }
13458
13459 // Now take care of the next serialized one...
13460
13461 // If we are waiting for a process to come up to handle the next
13462 // broadcast, then do nothing at this point. Just in case, we
13463 // check that the process we're waiting for still exists.
13464 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013465 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013466 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013467 + mPendingBroadcast.curApp);
13468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013469
13470 boolean isDead;
13471 synchronized (mPidsSelfLocked) {
13472 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13473 }
13474 if (!isDead) {
13475 // It's still alive, so keep waiting
13476 return;
13477 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013478 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013479 + " died before responding to broadcast");
13480 mPendingBroadcast = null;
13481 }
13482 }
13483
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013484 boolean looped = false;
13485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013486 do {
13487 if (mOrderedBroadcasts.size() == 0) {
13488 // No more broadcasts pending, so all done!
13489 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013490 if (looped) {
13491 // If we had finished the last ordered broadcast, then
13492 // make sure all processes have correct oom and sched
13493 // adjustments.
13494 updateOomAdjLocked();
13495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013496 return;
13497 }
13498 r = mOrderedBroadcasts.get(0);
13499 boolean forceReceive = false;
13500
13501 // Ensure that even if something goes awry with the timeout
13502 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013503 // and continue to make progress.
13504 //
13505 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
13506 // receivers don't get executed with with timeouts. They're intended for
13507 // one time heavy lifting after system upgrades and can take
13508 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013509 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013510 if (mSystemReady && r.dispatchTime > 0) {
13511 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013512 if ((numReceivers > 0) &&
13513 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013514 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013515 + " now=" + now
13516 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013517 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013518 + " intent=" + r.intent
13519 + " numReceivers=" + numReceivers
13520 + " nextReceiver=" + r.nextReceiver
13521 + " state=" + r.state);
13522 broadcastTimeout(); // forcibly finish this broadcast
13523 forceReceive = true;
13524 r.state = BroadcastRecord.IDLE;
13525 }
13526 }
13527
13528 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013529 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013530 "processNextBroadcast() called when not idle (state="
13531 + r.state + ")");
13532 return;
13533 }
13534
13535 if (r.receivers == null || r.nextReceiver >= numReceivers
13536 || r.resultAbort || forceReceive) {
13537 // No more receivers for this broadcast! Send the final
13538 // result if requested...
13539 if (r.resultTo != null) {
13540 try {
13541 if (DEBUG_BROADCAST) {
13542 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013543 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013544 + " seq=" + seq + " app=" + r.callerApp);
13545 }
13546 performReceive(r.callerApp, r.resultTo,
13547 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013548 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013549 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013550 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013551 }
13552 }
13553
Joe Onorato8a9b2202010-02-26 18:56:32 -080013554 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013555 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13556
Joe Onorato8a9b2202010-02-26 18:56:32 -080013557 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013558 + r);
13559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013560 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013561 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013562 mOrderedBroadcasts.remove(0);
13563 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013564 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013565 continue;
13566 }
13567 } while (r == null);
13568
13569 // Get the next receiver...
13570 int recIdx = r.nextReceiver++;
13571
13572 // Keep track of when this receiver started, and make sure there
13573 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013574 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013575 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013576 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013577
Joe Onorato8a9b2202010-02-26 18:56:32 -080013578 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013579 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013580 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013581 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013582 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013583 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013584 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013585 }
13586
13587 Object nextReceiver = r.receivers.get(recIdx);
13588 if (nextReceiver instanceof BroadcastFilter) {
13589 // Simple case: this is a registered receiver who gets
13590 // a direct call.
13591 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013592 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013593 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013594 + filter + ": " + r);
13595 deliverToRegisteredReceiver(r, filter, r.ordered);
13596 if (r.receiver == null || !r.ordered) {
13597 // The receiver has already finished, so schedule to
13598 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013599 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13600 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013601 r.state = BroadcastRecord.IDLE;
13602 scheduleBroadcastsLocked();
13603 }
13604 return;
13605 }
13606
13607 // Hard case: need to instantiate the receiver, possibly
13608 // starting its application process to host it.
13609
13610 ResolveInfo info =
13611 (ResolveInfo)nextReceiver;
13612
13613 boolean skip = false;
13614 int perm = checkComponentPermission(info.activityInfo.permission,
13615 r.callingPid, r.callingUid,
13616 info.activityInfo.exported
13617 ? -1 : info.activityInfo.applicationInfo.uid);
13618 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013619 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013620 + r.intent.toString()
13621 + " from " + r.callerPackage + " (pid=" + r.callingPid
13622 + ", uid=" + r.callingUid + ")"
13623 + " requires " + info.activityInfo.permission
13624 + " due to receiver " + info.activityInfo.packageName
13625 + "/" + info.activityInfo.name);
13626 skip = true;
13627 }
13628 if (r.callingUid != Process.SYSTEM_UID &&
13629 r.requiredPermission != null) {
13630 try {
13631 perm = ActivityThread.getPackageManager().
13632 checkPermission(r.requiredPermission,
13633 info.activityInfo.applicationInfo.packageName);
13634 } catch (RemoteException e) {
13635 perm = PackageManager.PERMISSION_DENIED;
13636 }
13637 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013638 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013639 + r.intent + " to "
13640 + info.activityInfo.applicationInfo.packageName
13641 + " requires " + r.requiredPermission
13642 + " due to sender " + r.callerPackage
13643 + " (uid " + r.callingUid + ")");
13644 skip = true;
13645 }
13646 }
13647 if (r.curApp != null && r.curApp.crashing) {
13648 // If the target process is crashing, just skip it.
13649 skip = true;
13650 }
13651
13652 if (skip) {
13653 r.receiver = null;
13654 r.curFilter = null;
13655 r.state = BroadcastRecord.IDLE;
13656 scheduleBroadcastsLocked();
13657 return;
13658 }
13659
13660 r.state = BroadcastRecord.APP_RECEIVE;
13661 String targetProcess = info.activityInfo.processName;
13662 r.curComponent = new ComponentName(
13663 info.activityInfo.applicationInfo.packageName,
13664 info.activityInfo.name);
13665 r.curReceiver = info.activityInfo;
13666
13667 // Is this receiver's application already running?
13668 ProcessRecord app = getProcessRecordLocked(targetProcess,
13669 info.activityInfo.applicationInfo.uid);
13670 if (app != null && app.thread != null) {
13671 try {
13672 processCurBroadcastLocked(r, app);
13673 return;
13674 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013675 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013676 + r.curComponent, e);
13677 }
13678
13679 // If a dead object exception was thrown -- fall through to
13680 // restart the application.
13681 }
13682
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013683 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013684 if ((r.curApp=startProcessLocked(targetProcess,
13685 info.activityInfo.applicationInfo, true,
13686 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013687 "broadcast", r.curComponent,
13688 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13689 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013690 // Ah, this recipient is unavailable. Finish it if necessary,
13691 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013692 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013693 + info.activityInfo.applicationInfo.packageName + "/"
13694 + info.activityInfo.applicationInfo.uid + " for broadcast "
13695 + r.intent + ": process is bad");
13696 logBroadcastReceiverDiscard(r);
13697 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13698 r.resultExtras, r.resultAbort, true);
13699 scheduleBroadcastsLocked();
13700 r.state = BroadcastRecord.IDLE;
13701 return;
13702 }
13703
13704 mPendingBroadcast = r;
13705 }
13706 }
13707
13708 // =========================================================
13709 // INSTRUMENTATION
13710 // =========================================================
13711
13712 public boolean startInstrumentation(ComponentName className,
13713 String profileFile, int flags, Bundle arguments,
13714 IInstrumentationWatcher watcher) {
13715 // Refuse possible leaked file descriptors
13716 if (arguments != null && arguments.hasFileDescriptors()) {
13717 throw new IllegalArgumentException("File descriptors passed in Bundle");
13718 }
13719
13720 synchronized(this) {
13721 InstrumentationInfo ii = null;
13722 ApplicationInfo ai = null;
13723 try {
13724 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013725 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013726 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013727 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013728 } catch (PackageManager.NameNotFoundException e) {
13729 }
13730 if (ii == null) {
13731 reportStartInstrumentationFailure(watcher, className,
13732 "Unable to find instrumentation info for: " + className);
13733 return false;
13734 }
13735 if (ai == null) {
13736 reportStartInstrumentationFailure(watcher, className,
13737 "Unable to find instrumentation target package: " + ii.targetPackage);
13738 return false;
13739 }
13740
13741 int match = mContext.getPackageManager().checkSignatures(
13742 ii.targetPackage, ii.packageName);
13743 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13744 String msg = "Permission Denial: starting instrumentation "
13745 + className + " from pid="
13746 + Binder.getCallingPid()
13747 + ", uid=" + Binder.getCallingPid()
13748 + " not allowed because package " + ii.packageName
13749 + " does not have a signature matching the target "
13750 + ii.targetPackage;
13751 reportStartInstrumentationFailure(watcher, className, msg);
13752 throw new SecurityException(msg);
13753 }
13754
13755 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013756 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013757 ProcessRecord app = addAppLocked(ai);
13758 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013759 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013760 app.instrumentationProfileFile = profileFile;
13761 app.instrumentationArguments = arguments;
13762 app.instrumentationWatcher = watcher;
13763 app.instrumentationResultClass = className;
13764 Binder.restoreCallingIdentity(origId);
13765 }
13766
13767 return true;
13768 }
13769
13770 /**
13771 * Report errors that occur while attempting to start Instrumentation. Always writes the
13772 * error to the logs, but if somebody is watching, send the report there too. This enables
13773 * the "am" command to report errors with more information.
13774 *
13775 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13776 * @param cn The component name of the instrumentation.
13777 * @param report The error report.
13778 */
13779 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13780 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013781 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013782 try {
13783 if (watcher != null) {
13784 Bundle results = new Bundle();
13785 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13786 results.putString("Error", report);
13787 watcher.instrumentationStatus(cn, -1, results);
13788 }
13789 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013790 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013791 }
13792 }
13793
13794 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13795 if (app.instrumentationWatcher != null) {
13796 try {
13797 // NOTE: IInstrumentationWatcher *must* be oneway here
13798 app.instrumentationWatcher.instrumentationFinished(
13799 app.instrumentationClass,
13800 resultCode,
13801 results);
13802 } catch (RemoteException e) {
13803 }
13804 }
13805 app.instrumentationWatcher = null;
13806 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013807 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013808 app.instrumentationProfileFile = null;
13809 app.instrumentationArguments = null;
13810
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013811 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013812 }
13813
13814 public void finishInstrumentation(IApplicationThread target,
13815 int resultCode, Bundle results) {
13816 // Refuse possible leaked file descriptors
13817 if (results != null && results.hasFileDescriptors()) {
13818 throw new IllegalArgumentException("File descriptors passed in Intent");
13819 }
13820
13821 synchronized(this) {
13822 ProcessRecord app = getRecordForAppLocked(target);
13823 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013824 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013825 return;
13826 }
13827 final long origId = Binder.clearCallingIdentity();
13828 finishInstrumentationLocked(app, resultCode, results);
13829 Binder.restoreCallingIdentity(origId);
13830 }
13831 }
13832
13833 // =========================================================
13834 // CONFIGURATION
13835 // =========================================================
13836
13837 public ConfigurationInfo getDeviceConfigurationInfo() {
13838 ConfigurationInfo config = new ConfigurationInfo();
13839 synchronized (this) {
13840 config.reqTouchScreen = mConfiguration.touchscreen;
13841 config.reqKeyboardType = mConfiguration.keyboard;
13842 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013843 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13844 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013845 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13846 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013847 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13848 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013849 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13850 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013851 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013852 }
13853 return config;
13854 }
13855
13856 public Configuration getConfiguration() {
13857 Configuration ci;
13858 synchronized(this) {
13859 ci = new Configuration(mConfiguration);
13860 }
13861 return ci;
13862 }
13863
13864 public void updateConfiguration(Configuration values) {
13865 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13866 "updateConfiguration()");
13867
13868 synchronized(this) {
13869 if (values == null && mWindowManager != null) {
13870 // sentinel: fetch the current configuration from the window manager
13871 values = mWindowManager.computeNewConfiguration();
13872 }
13873
13874 final long origId = Binder.clearCallingIdentity();
13875 updateConfigurationLocked(values, null);
13876 Binder.restoreCallingIdentity(origId);
13877 }
13878 }
13879
13880 /**
13881 * Do either or both things: (1) change the current configuration, and (2)
13882 * make sure the given activity is running with the (now) current
13883 * configuration. Returns true if the activity has been left running, or
13884 * false if <var>starting</var> is being destroyed to match the new
13885 * configuration.
13886 */
13887 public boolean updateConfigurationLocked(Configuration values,
13888 HistoryRecord starting) {
13889 int changes = 0;
13890
13891 boolean kept = true;
13892
13893 if (values != null) {
13894 Configuration newConfig = new Configuration(mConfiguration);
13895 changes = newConfig.updateFrom(values);
13896 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013897 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013898 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013899 }
13900
Doug Zongker2bec3d42009-12-04 12:52:44 -080013901 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013902
13903 if (values.locale != null) {
13904 saveLocaleLocked(values.locale,
13905 !values.locale.equals(mConfiguration.locale),
13906 values.userSetLocale);
13907 }
13908
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013909 mConfigurationSeq++;
13910 if (mConfigurationSeq <= 0) {
13911 mConfigurationSeq = 1;
13912 }
13913 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013914 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013915 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013916
13917 AttributeCache ac = AttributeCache.instance();
13918 if (ac != null) {
13919 ac.updateConfiguration(mConfiguration);
13920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013921
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013922 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13923 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13924 msg.obj = new Configuration(mConfiguration);
13925 mHandler.sendMessage(msg);
13926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013927
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013928 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13929 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013930 try {
13931 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013932 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013933 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013934 app.thread.scheduleConfigurationChanged(mConfiguration);
13935 }
13936 } catch (Exception e) {
13937 }
13938 }
13939 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013940 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13941 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013942 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13943 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013944 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13945 broadcastIntentLocked(null, null,
13946 new Intent(Intent.ACTION_LOCALE_CHANGED),
13947 null, null, 0, null, null,
13948 null, false, false, MY_PID, Process.SYSTEM_UID);
13949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013950 }
13951 }
13952
13953 if (changes != 0 && starting == null) {
13954 // If the configuration changed, and the caller is not already
13955 // in the process of starting an activity, then find the top
13956 // activity to check if its configuration needs to change.
13957 starting = topRunningActivityLocked(null);
13958 }
13959
13960 if (starting != null) {
13961 kept = ensureActivityConfigurationLocked(starting, changes);
13962 if (kept) {
13963 // If this didn't result in the starting activity being
13964 // destroyed, then we need to make sure at this point that all
13965 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013966 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013967 + ", ensuring others are correct.");
13968 ensureActivitiesVisibleLocked(starting, changes);
13969 }
13970 }
13971
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013972 if (values != null && mWindowManager != null) {
13973 mWindowManager.setNewConfiguration(mConfiguration);
13974 }
13975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013976 return kept;
13977 }
13978
13979 private final boolean relaunchActivityLocked(HistoryRecord r,
13980 int changes, boolean andResume) {
13981 List<ResultInfo> results = null;
13982 List<Intent> newIntents = null;
13983 if (andResume) {
13984 results = r.results;
13985 newIntents = r.newIntents;
13986 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013987 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013988 + " with results=" + results + " newIntents=" + newIntents
13989 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013990 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13991 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013992 r.task.taskId, r.shortComponentName);
13993
13994 r.startFreezingScreenLocked(r.app, 0);
13995
13996 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013997 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013998 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013999 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014000 // Note: don't need to call pauseIfSleepingLocked() here, because
14001 // the caller will only pass in 'andResume' if this activity is
14002 // currently resumed, which implies we aren't sleeping.
14003 } catch (RemoteException e) {
14004 return false;
14005 }
14006
14007 if (andResume) {
14008 r.results = null;
14009 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070014010 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014011 }
14012
14013 return true;
14014 }
14015
14016 /**
14017 * Make sure the given activity matches the current configuration. Returns
14018 * false if the activity had to be destroyed. Returns true if the
14019 * configuration is the same, or the activity will remain running as-is
14020 * for whatever reason. Ensures the HistoryRecord is updated with the
14021 * correct configuration and all other bookkeeping is handled.
14022 */
14023 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
14024 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070014025 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070014026 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
14027 "Skipping config check (will change): " + r);
14028 return true;
14029 }
14030
Joe Onorato8a9b2202010-02-26 18:56:32 -080014031 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014032 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014033
14034 // Short circuit: if the two configurations are the exact same
14035 // object (the common case), then there is nothing to do.
14036 Configuration newConfig = mConfiguration;
14037 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014038 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014039 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014040 return true;
14041 }
14042
14043 // We don't worry about activities that are finishing.
14044 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014045 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014046 "Configuration doesn't matter in finishing " + r);
14047 r.stopFreezingScreenLocked(false);
14048 return true;
14049 }
14050
14051 // Okay we now are going to make this activity have the new config.
14052 // But then we need to figure out how it needs to deal with that.
14053 Configuration oldConfig = r.configuration;
14054 r.configuration = newConfig;
14055
14056 // If the activity isn't currently running, just leave the new
14057 // configuration and it will pick that up next time it starts.
14058 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014059 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014060 "Configuration doesn't matter not running " + r);
14061 r.stopFreezingScreenLocked(false);
14062 return true;
14063 }
14064
14065 // If the activity isn't persistent, there is a chance we will
14066 // need to restart it.
14067 if (!r.persistent) {
14068
14069 // Figure out what has changed between the two configurations.
14070 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014071 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014072 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014073 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014074 + Integer.toHexString(r.info.configChanges)
14075 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014076 }
14077 if ((changes&(~r.info.configChanges)) != 0) {
14078 // Aha, the activity isn't handling the change, so DIE DIE DIE.
14079 r.configChangeFlags |= changes;
14080 r.startFreezingScreenLocked(r.app, globalChanges);
14081 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014082 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014083 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014084 destroyActivityLocked(r, true);
14085 } else if (r.state == ActivityState.PAUSING) {
14086 // A little annoying: we are waiting for this activity to
14087 // finish pausing. Let's not do anything now, but just
14088 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014089 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014090 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014091 r.configDestroy = true;
14092 return true;
14093 } else if (r.state == ActivityState.RESUMED) {
14094 // Try to optimize this case: the configuration is changing
14095 // and we need to restart the top, resumed activity.
14096 // Instead of doing the normal handshaking, just say
14097 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080014098 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014099 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014100 relaunchActivityLocked(r, r.configChangeFlags, true);
14101 r.configChangeFlags = 0;
14102 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014103 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014104 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014105 relaunchActivityLocked(r, r.configChangeFlags, false);
14106 r.configChangeFlags = 0;
14107 }
14108
14109 // All done... tell the caller we weren't able to keep this
14110 // activity around.
14111 return false;
14112 }
14113 }
14114
14115 // Default case: the activity can handle this new configuration, so
14116 // hand it over. Note that we don't need to give it the new
14117 // configuration, since we always send configuration changes to all
14118 // process when they happen so it can just use whatever configuration
14119 // it last got.
14120 if (r.app != null && r.app.thread != null) {
14121 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014122 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014123 r.app.thread.scheduleActivityConfigurationChanged(r);
14124 } catch (RemoteException e) {
14125 // If process died, whatever.
14126 }
14127 }
14128 r.stopFreezingScreenLocked(false);
14129
14130 return true;
14131 }
14132
14133 /**
14134 * Save the locale. You must be inside a synchronized (this) block.
14135 */
14136 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
14137 if(isDiff) {
14138 SystemProperties.set("user.language", l.getLanguage());
14139 SystemProperties.set("user.region", l.getCountry());
14140 }
14141
14142 if(isPersist) {
14143 SystemProperties.set("persist.sys.language", l.getLanguage());
14144 SystemProperties.set("persist.sys.country", l.getCountry());
14145 SystemProperties.set("persist.sys.localevar", l.getVariant());
14146 }
14147 }
14148
14149 // =========================================================
14150 // LIFETIME MANAGEMENT
14151 // =========================================================
14152
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014153 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
14154 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014155 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014156 // This adjustment has already been computed. If we are calling
14157 // from the top, we may have already computed our adjustment with
14158 // an earlier hidden adjustment that isn't really for us... if
14159 // so, use the new hidden adjustment.
14160 if (!recursed && app.hidden) {
14161 app.curAdj = hiddenAdj;
14162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014163 return app.curAdj;
14164 }
14165
14166 if (app.thread == null) {
14167 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014168 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014169 return (app.curAdj=EMPTY_APP_ADJ);
14170 }
14171
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014172 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
14173 // The max adjustment doesn't allow this app to be anything
14174 // below foreground, so it is not worth doing work for it.
14175 app.adjType = "fixed";
14176 app.adjSeq = mAdjSeq;
14177 app.curRawAdj = app.maxAdj;
14178 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
14179 return (app.curAdj=app.maxAdj);
14180 }
14181
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014182 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014183 app.adjSource = null;
14184 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014185 app.empty = false;
14186 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014187
The Android Open Source Project4df24232009-03-05 14:34:35 -080014188 // Determine the importance of the process, starting with most
14189 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014190 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014191 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014192 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014193 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014194 // The last app on the list is the foreground app.
14195 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014196 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014197 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014198 } else if (app.instrumentationClass != null) {
14199 // Don't want to kill running instrumentation.
14200 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014201 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014202 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014203 } else if (app.persistentActivities > 0) {
14204 // Special persistent activities... shouldn't be used these days.
14205 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014206 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014207 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014208 } else if (app.curReceiver != null ||
14209 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
14210 // An app that is currently receiving a broadcast also
14211 // counts as being in the foreground.
14212 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014213 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014214 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014215 } else if (app.executingServices.size() > 0) {
14216 // An app that is currently executing a service callback also
14217 // counts as being in the foreground.
14218 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014219 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014220 app.adjType = "exec-service";
14221 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014222 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014223 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014224 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014225 app.adjType = "foreground-service";
14226 } else if (app.forcingToForeground != null) {
14227 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014228 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014229 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014230 app.adjType = "force-foreground";
14231 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014232 } else if (app == mHeavyWeightProcess) {
14233 // We don't want to kill the current heavy-weight process.
14234 adj = HEAVY_WEIGHT_APP_ADJ;
14235 schedGroup = Process.THREAD_GROUP_DEFAULT;
14236 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080014237 } else if (app == mHomeProcess) {
14238 // This process is hosting what we currently consider to be the
14239 // home app, so we don't want to let it go into the background.
14240 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014241 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014242 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014243 } else if ((N=app.activities.size()) != 0) {
14244 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014245 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014246 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014247 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014248 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014249 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014250 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014251 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014252 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014253 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014254 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014255 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014256 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014257 break;
14258 }
14259 }
14260 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014261 // A very not-needed process. If this is lower in the lru list,
14262 // we will push it in to the empty bucket.
14263 app.hidden = true;
14264 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014265 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014266 adj = hiddenAdj;
14267 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014268 }
14269
Joe Onorato8a9b2202010-02-26 18:56:32 -080014270 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014271
The Android Open Source Project4df24232009-03-05 14:34:35 -080014272 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014273 // there are applications dependent on our services or providers, but
14274 // this gives us a baseline and makes sure we don't get into an
14275 // infinite recursion.
14276 app.adjSeq = mAdjSeq;
14277 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014278
Christopher Tate6fa95972009-06-05 18:43:55 -070014279 if (mBackupTarget != null && app == mBackupTarget.app) {
14280 // If possible we want to avoid killing apps while they're being backed up
14281 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014282 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070014283 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014284 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014285 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070014286 }
14287 }
14288
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014289 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
14290 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014291 final long now = SystemClock.uptimeMillis();
14292 // This process is more important if the top activity is
14293 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070014294 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014295 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014296 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014297 if (s.startRequested) {
14298 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14299 // This service has seen some activity within
14300 // recent memory, so we will keep its process ahead
14301 // of the background processes.
14302 if (adj > SECONDARY_SERVER_ADJ) {
14303 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014304 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014305 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014306 }
14307 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014308 // If we have let the service slide into the background
14309 // state, still have some text describing what it is doing
14310 // even though the service no longer has an impact.
14311 if (adj > SECONDARY_SERVER_ADJ) {
14312 app.adjType = "started-bg-services";
14313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014314 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014315 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
14316 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014317 Iterator<ConnectionRecord> kt
14318 = s.connections.values().iterator();
14319 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14320 // XXX should compute this based on the max of
14321 // all connected clients.
14322 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014323 if (cr.binding.client == app) {
14324 // Binding to ourself is not interesting.
14325 continue;
14326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014327 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
14328 ProcessRecord client = cr.binding.client;
14329 int myHiddenAdj = hiddenAdj;
14330 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014331 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014332 myHiddenAdj = client.hiddenAdj;
14333 } else {
14334 myHiddenAdj = VISIBLE_APP_ADJ;
14335 }
14336 }
14337 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014338 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014339 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014340 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014341 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014342 if (!client.hidden) {
14343 app.hidden = false;
14344 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014345 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014346 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14347 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014348 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014349 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014350 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014351 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14352 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14353 schedGroup = Process.THREAD_GROUP_DEFAULT;
14354 }
14355 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014356 }
14357 HistoryRecord a = cr.activity;
14358 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014359 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014360 //}
14361 if (a != null && adj > FOREGROUND_APP_ADJ &&
14362 (a.state == ActivityState.RESUMED
14363 || a.state == ActivityState.PAUSING)) {
14364 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014365 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014366 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014367 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014368 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14369 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014370 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014371 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014372 }
14373 }
14374 }
14375 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014376
14377 // Finally, f this process has active services running in it, we
14378 // would like to avoid killing it unless it would prevent the current
14379 // application from running. By default we put the process in
14380 // with the rest of the background processes; as we scan through
14381 // its services we may bump it up from there.
14382 if (adj > hiddenAdj) {
14383 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014384 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014385 app.adjType = "bg-services";
14386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014387 }
14388
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014389 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
14390 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014391 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014392 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
14393 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014394 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014395 if (cpr.clients.size() != 0) {
14396 Iterator<ProcessRecord> kt = cpr.clients.iterator();
14397 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14398 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014399 if (client == app) {
14400 // Being our own client is not interesting.
14401 continue;
14402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014403 int myHiddenAdj = hiddenAdj;
14404 if (myHiddenAdj > client.hiddenAdj) {
14405 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
14406 myHiddenAdj = client.hiddenAdj;
14407 } else {
14408 myHiddenAdj = FOREGROUND_APP_ADJ;
14409 }
14410 }
14411 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014412 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014413 if (adj > clientAdj) {
14414 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014415 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014416 if (!client.hidden) {
14417 app.hidden = false;
14418 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014419 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014420 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14421 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014422 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014423 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014424 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014425 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14426 schedGroup = Process.THREAD_GROUP_DEFAULT;
14427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014428 }
14429 }
14430 // If the provider has external (non-framework) process
14431 // dependencies, ensure that its adjustment is at least
14432 // FOREGROUND_APP_ADJ.
14433 if (cpr.externals != 0) {
14434 if (adj > FOREGROUND_APP_ADJ) {
14435 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014436 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014437 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014438 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014439 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014440 }
14441 }
14442 }
14443 }
14444
14445 app.curRawAdj = adj;
14446
Joe Onorato8a9b2202010-02-26 18:56:32 -080014447 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014448 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14449 if (adj > app.maxAdj) {
14450 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014451 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014452 schedGroup = Process.THREAD_GROUP_DEFAULT;
14453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014454 }
14455
14456 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014457 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014459 return adj;
14460 }
14461
14462 /**
14463 * Ask a given process to GC right now.
14464 */
14465 final void performAppGcLocked(ProcessRecord app) {
14466 try {
14467 app.lastRequestedGc = SystemClock.uptimeMillis();
14468 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014469 if (app.reportLowMemory) {
14470 app.reportLowMemory = false;
14471 app.thread.scheduleLowMemory();
14472 } else {
14473 app.thread.processInBackground();
14474 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014475 }
14476 } catch (Exception e) {
14477 // whatever.
14478 }
14479 }
14480
14481 /**
14482 * Returns true if things are idle enough to perform GCs.
14483 */
Josh Bartel7f208742010-02-25 11:01:44 -060014484 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014485 return mParallelBroadcasts.size() == 0
14486 && mOrderedBroadcasts.size() == 0
14487 && (mSleeping || (mResumedActivity != null &&
14488 mResumedActivity.idle));
14489 }
14490
14491 /**
14492 * Perform GCs on all processes that are waiting for it, but only
14493 * if things are idle.
14494 */
14495 final void performAppGcsLocked() {
14496 final int N = mProcessesToGc.size();
14497 if (N <= 0) {
14498 return;
14499 }
Josh Bartel7f208742010-02-25 11:01:44 -060014500 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014501 while (mProcessesToGc.size() > 0) {
14502 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014503 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014504 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14505 <= SystemClock.uptimeMillis()) {
14506 // To avoid spamming the system, we will GC processes one
14507 // at a time, waiting a few seconds between each.
14508 performAppGcLocked(proc);
14509 scheduleAppGcsLocked();
14510 return;
14511 } else {
14512 // It hasn't been long enough since we last GCed this
14513 // process... put it in the list to wait for its time.
14514 addProcessToGcListLocked(proc);
14515 break;
14516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014517 }
14518 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014519
14520 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014521 }
14522 }
14523
14524 /**
14525 * If all looks good, perform GCs on all processes waiting for them.
14526 */
14527 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014528 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014529 performAppGcsLocked();
14530 return;
14531 }
14532 // Still not idle, wait some more.
14533 scheduleAppGcsLocked();
14534 }
14535
14536 /**
14537 * Schedule the execution of all pending app GCs.
14538 */
14539 final void scheduleAppGcsLocked() {
14540 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014541
14542 if (mProcessesToGc.size() > 0) {
14543 // Schedule a GC for the time to the next process.
14544 ProcessRecord proc = mProcessesToGc.get(0);
14545 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14546
14547 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14548 long now = SystemClock.uptimeMillis();
14549 if (when < (now+GC_TIMEOUT)) {
14550 when = now + GC_TIMEOUT;
14551 }
14552 mHandler.sendMessageAtTime(msg, when);
14553 }
14554 }
14555
14556 /**
14557 * Add a process to the array of processes waiting to be GCed. Keeps the
14558 * list in sorted order by the last GC time. The process can't already be
14559 * on the list.
14560 */
14561 final void addProcessToGcListLocked(ProcessRecord proc) {
14562 boolean added = false;
14563 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14564 if (mProcessesToGc.get(i).lastRequestedGc <
14565 proc.lastRequestedGc) {
14566 added = true;
14567 mProcessesToGc.add(i+1, proc);
14568 break;
14569 }
14570 }
14571 if (!added) {
14572 mProcessesToGc.add(0, proc);
14573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014574 }
14575
14576 /**
14577 * Set up to ask a process to GC itself. This will either do it
14578 * immediately, or put it on the list of processes to gc the next
14579 * time things are idle.
14580 */
14581 final void scheduleAppGcLocked(ProcessRecord app) {
14582 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014583 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014584 return;
14585 }
14586 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014587 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014588 scheduleAppGcsLocked();
14589 }
14590 }
14591
14592 private final boolean updateOomAdjLocked(
14593 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14594 app.hiddenAdj = hiddenAdj;
14595
14596 if (app.thread == null) {
14597 return true;
14598 }
14599
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014600 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014601
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014602 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014603 if (app.curRawAdj != app.setRawAdj) {
14604 if (app.curRawAdj > FOREGROUND_APP_ADJ
14605 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14606 // If this app is transitioning from foreground to
14607 // non-foreground, have it do a gc.
14608 scheduleAppGcLocked(app);
14609 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14610 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14611 // Likewise do a gc when an app is moving in to the
14612 // background (such as a service stopping).
14613 scheduleAppGcLocked(app);
14614 }
14615 app.setRawAdj = app.curRawAdj;
14616 }
14617 if (adj != app.setAdj) {
14618 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014619 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014620 TAG, "Set app " + app.processName +
14621 " oom adj to " + adj);
14622 app.setAdj = adj;
14623 } else {
14624 return false;
14625 }
14626 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014627 if (app.setSchedGroup != app.curSchedGroup) {
14628 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014629 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014630 "Setting process group of " + app.processName
14631 + " to " + app.curSchedGroup);
14632 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014633 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014634 try {
14635 Process.setProcessGroup(app.pid, app.curSchedGroup);
14636 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014637 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014638 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014639 e.printStackTrace();
14640 } finally {
14641 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014642 }
14643 }
14644 if (false) {
14645 if (app.thread != null) {
14646 try {
14647 app.thread.setSchedulingGroup(app.curSchedGroup);
14648 } catch (RemoteException e) {
14649 }
14650 }
14651 }
14652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014653 }
14654
14655 return true;
14656 }
14657
14658 private final HistoryRecord resumedAppLocked() {
14659 HistoryRecord resumedActivity = mResumedActivity;
14660 if (resumedActivity == null || resumedActivity.app == null) {
14661 resumedActivity = mPausingActivity;
14662 if (resumedActivity == null || resumedActivity.app == null) {
14663 resumedActivity = topRunningActivityLocked(null);
14664 }
14665 }
14666 return resumedActivity;
14667 }
14668
14669 private final boolean updateOomAdjLocked(ProcessRecord app) {
14670 final HistoryRecord TOP_ACT = resumedAppLocked();
14671 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14672 int curAdj = app.curAdj;
14673 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14674 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14675
14676 mAdjSeq++;
14677
14678 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14679 if (res) {
14680 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14681 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14682 if (nowHidden != wasHidden) {
14683 // Changed to/from hidden state, so apps after it in the LRU
14684 // list may also be changed.
14685 updateOomAdjLocked();
14686 }
14687 }
14688 return res;
14689 }
14690
14691 private final boolean updateOomAdjLocked() {
14692 boolean didOomAdj = true;
14693 final HistoryRecord TOP_ACT = resumedAppLocked();
14694 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14695
14696 if (false) {
14697 RuntimeException e = new RuntimeException();
14698 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014699 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014700 }
14701
14702 mAdjSeq++;
14703
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014704 // Let's determine how many processes we have running vs.
14705 // how many slots we have for background processes; we may want
14706 // to put multiple processes in a slot of there are enough of
14707 // them.
14708 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14709 int factor = (mLruProcesses.size()-4)/numSlots;
14710 if (factor < 1) factor = 1;
14711 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014712 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014714 // First try updating the OOM adjustment for each of the
14715 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014716 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014717 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14718 while (i > 0) {
14719 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014720 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014721 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014722 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014723 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014724 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014725 step++;
14726 if (step >= factor) {
14727 step = 0;
14728 curHiddenAdj++;
14729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014730 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014731 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070014732 if (!app.killedBackground) {
14733 numHidden++;
14734 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070014735 Slog.i(TAG, "No longer want " + app.processName
14736 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014737 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14738 app.processName, app.setAdj, "too many background");
14739 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070014740 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014741 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014742 }
14743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014744 } else {
14745 didOomAdj = false;
14746 }
14747 }
14748
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014749 // If we return false, we will fall back on killing processes to
14750 // have a fixed limit. Do this if a limit has been requested; else
14751 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014752 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14753 }
14754
14755 private final void trimApplications() {
14756 synchronized (this) {
14757 int i;
14758
14759 // First remove any unused application processes whose package
14760 // has been removed.
14761 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14762 final ProcessRecord app = mRemovedProcesses.get(i);
14763 if (app.activities.size() == 0
14764 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014765 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014766 TAG, "Exiting empty application process "
14767 + app.processName + " ("
14768 + (app.thread != null ? app.thread.asBinder() : null)
14769 + ")\n");
14770 if (app.pid > 0 && app.pid != MY_PID) {
14771 Process.killProcess(app.pid);
14772 } else {
14773 try {
14774 app.thread.scheduleExit();
14775 } catch (Exception e) {
14776 // Ignore exceptions.
14777 }
14778 }
14779 cleanUpApplicationRecordLocked(app, false, -1);
14780 mRemovedProcesses.remove(i);
14781
14782 if (app.persistent) {
14783 if (app.persistent) {
14784 addAppLocked(app.info);
14785 }
14786 }
14787 }
14788 }
14789
14790 // Now try updating the OOM adjustment for each of the
14791 // application processes based on their current state.
14792 // If the setOomAdj() API is not supported, then go with our
14793 // back-up plan...
14794 if (!updateOomAdjLocked()) {
14795
14796 // Count how many processes are running services.
14797 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014798 for (i=mLruProcesses.size()-1; i>=0; i--) {
14799 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014800
14801 if (app.persistent || app.services.size() != 0
14802 || app.curReceiver != null
14803 || app.persistentActivities > 0) {
14804 // Don't count processes holding services against our
14805 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014806 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014807 TAG, "Not trimming app " + app + " with services: "
14808 + app.services);
14809 numServiceProcs++;
14810 }
14811 }
14812
14813 int curMaxProcs = mProcessLimit;
14814 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14815 if (mAlwaysFinishActivities) {
14816 curMaxProcs = 1;
14817 }
14818 curMaxProcs += numServiceProcs;
14819
14820 // Quit as many processes as we can to get down to the desired
14821 // process count. First remove any processes that no longer
14822 // have activites running in them.
14823 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014824 i<mLruProcesses.size()
14825 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014826 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014827 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014828 // Quit an application only if it is not currently
14829 // running any activities.
14830 if (!app.persistent && app.activities.size() == 0
14831 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014832 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014833 TAG, "Exiting empty application process "
14834 + app.processName + " ("
14835 + (app.thread != null ? app.thread.asBinder() : null)
14836 + ")\n");
14837 if (app.pid > 0 && app.pid != MY_PID) {
14838 Process.killProcess(app.pid);
14839 } else {
14840 try {
14841 app.thread.scheduleExit();
14842 } catch (Exception e) {
14843 // Ignore exceptions.
14844 }
14845 }
14846 // todo: For now we assume the application is not buggy
14847 // or evil, and will quit as a result of our request.
14848 // Eventually we need to drive this off of the death
14849 // notification, and kill the process if it takes too long.
14850 cleanUpApplicationRecordLocked(app, false, i);
14851 i--;
14852 }
14853 }
14854
14855 // If we still have too many processes, now from the least
14856 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014857 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014858 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014859 " of " + curMaxProcs + " processes");
14860 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014861 i<mLruProcesses.size()
14862 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014863 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014864 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014865 // Quit the application only if we have a state saved for
14866 // all of its activities.
14867 boolean canQuit = !app.persistent && app.curReceiver == null
14868 && app.services.size() == 0
14869 && app.persistentActivities == 0;
14870 int NUMA = app.activities.size();
14871 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014872 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014873 TAG, "Looking to quit " + app.processName);
14874 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014875 HistoryRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014876 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014877 TAG, " " + r.intent.getComponent().flattenToShortString()
14878 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14879 canQuit = (r.haveState || !r.stateNotNeeded)
14880 && !r.visible && r.stopped;
14881 }
14882 if (canQuit) {
14883 // Finish all of the activities, and then the app itself.
14884 for (j=0; j<NUMA; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014885 HistoryRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014886 if (!r.finishing) {
14887 destroyActivityLocked(r, false);
14888 }
14889 r.resultTo = null;
14890 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014891 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014892 + app.processName + " ("
14893 + (app.thread != null ? app.thread.asBinder() : null)
14894 + ")\n");
14895 if (app.pid > 0 && app.pid != MY_PID) {
14896 Process.killProcess(app.pid);
14897 } else {
14898 try {
14899 app.thread.scheduleExit();
14900 } catch (Exception e) {
14901 // Ignore exceptions.
14902 }
14903 }
14904 // todo: For now we assume the application is not buggy
14905 // or evil, and will quit as a result of our request.
14906 // Eventually we need to drive this off of the death
14907 // notification, and kill the process if it takes too long.
14908 cleanUpApplicationRecordLocked(app, false, i);
14909 i--;
14910 //dump();
14911 }
14912 }
14913
14914 }
14915
14916 int curMaxActivities = MAX_ACTIVITIES;
14917 if (mAlwaysFinishActivities) {
14918 curMaxActivities = 1;
14919 }
14920
14921 // Finally, if there are too many activities now running, try to
14922 // finish as many as we can to get back down to the limit.
14923 for ( i=0;
14924 i<mLRUActivities.size()
14925 && mLRUActivities.size() > curMaxActivities;
14926 i++) {
14927 final HistoryRecord r
14928 = (HistoryRecord)mLRUActivities.get(i);
14929
14930 // We can finish this one if we have its icicle saved and
14931 // it is not persistent.
14932 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14933 && r.stopped && !r.persistent && !r.finishing) {
14934 final int origSize = mLRUActivities.size();
14935 destroyActivityLocked(r, true);
14936
14937 // This will remove it from the LRU list, so keep
14938 // our index at the same value. Note that this check to
14939 // see if the size changes is just paranoia -- if
14940 // something unexpected happens, we don't want to end up
14941 // in an infinite loop.
14942 if (origSize > mLRUActivities.size()) {
14943 i--;
14944 }
14945 }
14946 }
14947 }
14948 }
14949
14950 /** This method sends the specified signal to each of the persistent apps */
14951 public void signalPersistentProcesses(int sig) throws RemoteException {
14952 if (sig != Process.SIGNAL_USR1) {
14953 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14954 }
14955
14956 synchronized (this) {
14957 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14958 != PackageManager.PERMISSION_GRANTED) {
14959 throw new SecurityException("Requires permission "
14960 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14961 }
14962
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014963 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14964 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014965 if (r.thread != null && r.persistent) {
14966 Process.sendSignal(r.pid, sig);
14967 }
14968 }
14969 }
14970 }
14971
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014972 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014973 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014974
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014975 try {
14976 synchronized (this) {
14977 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14978 // its own permission.
14979 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14980 != PackageManager.PERMISSION_GRANTED) {
14981 throw new SecurityException("Requires permission "
14982 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014983 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014984
14985 if (start && fd == null) {
14986 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014987 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014988
14989 ProcessRecord proc = null;
14990 try {
14991 int pid = Integer.parseInt(process);
14992 synchronized (mPidsSelfLocked) {
14993 proc = mPidsSelfLocked.get(pid);
14994 }
14995 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014996 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014997
14998 if (proc == null) {
14999 HashMap<String, SparseArray<ProcessRecord>> all
15000 = mProcessNames.getMap();
15001 SparseArray<ProcessRecord> procs = all.get(process);
15002 if (procs != null && procs.size() > 0) {
15003 proc = procs.valueAt(0);
15004 }
15005 }
15006
15007 if (proc == null || proc.thread == null) {
15008 throw new IllegalArgumentException("Unknown process: " + process);
15009 }
15010
15011 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
15012 if (isSecure) {
15013 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
15014 throw new SecurityException("Process not debuggable: " + proc);
15015 }
15016 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015017
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015018 proc.thread.profilerControl(start, path, fd);
15019 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015020 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015021 }
15022 } catch (RemoteException e) {
15023 throw new IllegalStateException("Process disappeared");
15024 } finally {
15025 if (fd != null) {
15026 try {
15027 fd.close();
15028 } catch (IOException e) {
15029 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015030 }
15031 }
15032 }
15033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015034 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
15035 public void monitor() {
15036 synchronized (this) { }
15037 }
15038}