blob: e93f7ff2c66978bd14a944bcffe52f8260728a22 [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 /**
651 * Intent broadcast that we have tried to start, but are
652 * waiting for its application's process to be created. We only
653 * need one (instead of a list) because we always process broadcasts
654 * one at a time, so no others can be started while waiting for this
655 * one.
656 */
657 BroadcastRecord mPendingBroadcast = null;
658
659 /**
660 * Keeps track of all IIntentReceivers that have been registered for
661 * broadcasts. Hash keys are the receiver IBinder, hash value is
662 * a ReceiverList.
663 */
664 final HashMap mRegisteredReceivers = new HashMap();
665
666 /**
667 * Resolver for broadcast intents to registered receivers.
668 * Holds BroadcastFilter (subclass of IntentFilter).
669 */
670 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
671 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
672 @Override
673 protected boolean allowFilterResult(
674 BroadcastFilter filter, List<BroadcastFilter> dest) {
675 IBinder target = filter.receiverList.receiver.asBinder();
676 for (int i=dest.size()-1; i>=0; i--) {
677 if (dest.get(i).receiverList.receiver.asBinder() == target) {
678 return false;
679 }
680 }
681 return true;
682 }
683 };
684
685 /**
686 * State of all active sticky broadcasts. Keys are the action of the
687 * sticky Intent, values are an ArrayList of all broadcasted intents with
688 * that action (which should usually be one).
689 */
690 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
691 new HashMap<String, ArrayList<Intent>>();
692
693 /**
694 * All currently running services.
695 */
696 final HashMap<ComponentName, ServiceRecord> mServices =
697 new HashMap<ComponentName, ServiceRecord>();
698
699 /**
700 * All currently running services indexed by the Intent used to start them.
701 */
702 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
703 new HashMap<Intent.FilterComparison, ServiceRecord>();
704
705 /**
706 * All currently bound service connections. Keys are the IBinder of
707 * the client's IServiceConnection.
708 */
709 final HashMap<IBinder, ConnectionRecord> mServiceConnections
710 = new HashMap<IBinder, ConnectionRecord>();
711
712 /**
713 * List of services that we have been asked to start,
714 * but haven't yet been able to. It is used to hold start requests
715 * while waiting for their corresponding application thread to get
716 * going.
717 */
718 final ArrayList<ServiceRecord> mPendingServices
719 = new ArrayList<ServiceRecord>();
720
721 /**
722 * List of services that are scheduled to restart following a crash.
723 */
724 final ArrayList<ServiceRecord> mRestartingServices
725 = new ArrayList<ServiceRecord>();
726
727 /**
728 * List of services that are in the process of being stopped.
729 */
730 final ArrayList<ServiceRecord> mStoppingServices
731 = new ArrayList<ServiceRecord>();
732
733 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700734 * Backup/restore process management
735 */
736 String mBackupAppName = null;
737 BackupRecord mBackupTarget = null;
738
739 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 * List of PendingThumbnailsRecord objects of clients who are still
741 * waiting to receive all of the thumbnails for a task.
742 */
743 final ArrayList mPendingThumbnails = new ArrayList();
744
745 /**
746 * List of HistoryRecord objects that have been finished and must
747 * still report back to a pending thumbnail receiver.
748 */
749 final ArrayList mCancelledThumbnails = new ArrayList();
750
751 /**
752 * All of the currently running global content providers. Keys are a
753 * string containing the provider name and values are a
754 * ContentProviderRecord object containing the data about it. Note
755 * that a single provider may be published under multiple names, so
756 * there may be multiple entries here for a single one in mProvidersByClass.
757 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700758 final HashMap<String, ContentProviderRecord> mProvidersByName
759 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760
761 /**
762 * All of the currently running global content providers. Keys are a
763 * string containing the provider's implementation class and values are a
764 * ContentProviderRecord object containing the data about it.
765 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700766 final HashMap<String, ContentProviderRecord> mProvidersByClass
767 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768
769 /**
770 * List of content providers who have clients waiting for them. The
771 * application is currently being launched and the provider will be
772 * removed from this list once it is published.
773 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700774 final ArrayList<ContentProviderRecord> mLaunchingProviders
775 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776
777 /**
778 * Global set of specific Uri permissions that have been granted.
779 */
780 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
781 = new SparseArray<HashMap<Uri, UriPermission>>();
782
783 /**
784 * Thread-local storage used to carry caller permissions over through
785 * indirect content-provider access.
786 * @see #ActivityManagerService.openContentUri()
787 */
788 private class Identity {
789 public int pid;
790 public int uid;
791
792 Identity(int _pid, int _uid) {
793 pid = _pid;
794 uid = _uid;
795 }
796 }
797 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
798
799 /**
800 * All information we have collected about the runtime performance of
801 * any user id that can impact battery performance.
802 */
803 final BatteryStatsService mBatteryStatsService;
804
805 /**
806 * information about component usage
807 */
808 final UsageStatsService mUsageStatsService;
809
810 /**
811 * Current configuration information. HistoryRecord objects are given
812 * a reference to this object to indicate which configuration they are
813 * currently running in, so this object must be kept immutable.
814 */
815 Configuration mConfiguration = new Configuration();
816
817 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800818 * Current sequencing integer of the configuration, for skipping old
819 * configurations.
820 */
821 int mConfigurationSeq = 0;
822
823 /**
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700824 * Set when we know we are going to be calling updateConfiguration()
825 * soon, so want to skip intermediate config checks.
826 */
827 boolean mConfigWillChange;
828
829 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700830 * Hardware-reported OpenGLES version.
831 */
832 final int GL_ES_VERSION;
833
834 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 * List of initialization arguments to pass to all processes when binding applications to them.
836 * For example, references to the commonly used services.
837 */
838 HashMap<String, IBinder> mAppBindArgs;
839
840 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700841 * Temporary to avoid allocations. Protected by main lock.
842 */
843 final StringBuilder mStringBuilder = new StringBuilder(256);
844
845 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 * Used to control how we initialize the service.
847 */
848 boolean mStartRunning = false;
849 ComponentName mTopComponent;
850 String mTopAction;
851 String mTopData;
852 boolean mSystemReady = false;
853 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700854 boolean mWaitingUpdate = false;
855 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856
857 Context mContext;
858
859 int mFactoryTest;
860
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700861 boolean mCheckedForSetup;
862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700864 * The time at which we will allow normal application switches again,
865 * after a call to {@link #stopAppSwitches()}.
866 */
867 long mAppSwitchesAllowedTime;
868
869 /**
870 * This is set to true after the first switch after mAppSwitchesAllowedTime
871 * is set; any switches after that will clear the time.
872 */
873 boolean mDidAppSwitch;
874
875 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 * Set while we are wanting to sleep, to prevent any
877 * activities from being started/resumed.
878 */
879 boolean mSleeping = false;
880
881 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700882 * Set if we are shutting down the system, similar to sleeping.
883 */
884 boolean mShuttingDown = false;
885
886 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 * Set when the system is going to sleep, until we have
888 * successfully paused the current activity and released our wake lock.
889 * At that point the system is allowed to actually sleep.
890 */
891 PowerManager.WakeLock mGoingToSleep;
892
893 /**
894 * We don't want to allow the device to go to sleep while in the process
895 * of launching an activity. This is primarily to allow alarm intent
896 * receivers to launch an activity and get that to run before the device
897 * goes back to sleep.
898 */
899 PowerManager.WakeLock mLaunchingActivity;
900
901 /**
902 * Task identifier that activities are currently being started
903 * in. Incremented each time a new task is created.
904 * todo: Replace this with a TokenSpace class that generates non-repeating
905 * integers that won't wrap.
906 */
907 int mCurTask = 1;
908
909 /**
910 * Current sequence id for oom_adj computation traversal.
911 */
912 int mAdjSeq = 0;
913
914 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700915 * Current sequence id for process LRU updating.
916 */
917 int mLruSeq = 0;
918
919 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
921 * is set, indicating the user wants processes started in such a way
922 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
923 * running in each process (thus no pre-initialized process, etc).
924 */
925 boolean mSimpleProcessManagement = false;
926
927 /**
928 * System monitoring: number of processes that died since the last
929 * N procs were started.
930 */
931 int[] mProcDeaths = new int[20];
932
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700933 /**
934 * This is set if we had to do a delayed dexopt of an app before launching
935 * it, to increasing the ANR timeouts in that case.
936 */
937 boolean mDidDexOpt;
938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 String mDebugApp = null;
940 boolean mWaitForDebugger = false;
941 boolean mDebugTransient = false;
942 String mOrigDebugApp = null;
943 boolean mOrigWaitForDebugger = false;
944 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700945 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700947 final RemoteCallbackList<IActivityWatcher> mWatchers
948 = new RemoteCallbackList<IActivityWatcher>();
949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 /**
951 * Callback of last caller to {@link #requestPss}.
952 */
953 Runnable mRequestPssCallback;
954
955 /**
956 * Remaining processes for which we are waiting results from the last
957 * call to {@link #requestPss}.
958 */
959 final ArrayList<ProcessRecord> mRequestPssList
960 = new ArrayList<ProcessRecord>();
961
962 /**
963 * Runtime statistics collection thread. This object's lock is used to
964 * protect all related state.
965 */
966 final Thread mProcessStatsThread;
967
968 /**
969 * Used to collect process stats when showing not responding dialog.
970 * Protected by mProcessStatsThread.
971 */
972 final ProcessStats mProcessStats = new ProcessStats(
973 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700974 final AtomicLong mLastCpuTime = new AtomicLong(0);
975 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 long mLastWriteTime = 0;
978
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700979 long mInitialStartTime = 0;
980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 /**
982 * Set to true after the system has finished booting.
983 */
984 boolean mBooted = false;
985
986 int mProcessLimit = 0;
987
988 WindowManagerService mWindowManager;
989
990 static ActivityManagerService mSelf;
991 static ActivityThread mSystemThread;
992
993 private final class AppDeathRecipient implements IBinder.DeathRecipient {
994 final ProcessRecord mApp;
995 final int mPid;
996 final IApplicationThread mAppThread;
997
998 AppDeathRecipient(ProcessRecord app, int pid,
999 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001000 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 TAG, "New death recipient " + this
1002 + " for thread " + thread.asBinder());
1003 mApp = app;
1004 mPid = pid;
1005 mAppThread = thread;
1006 }
1007
1008 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001009 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 TAG, "Death received in " + this
1011 + " for thread " + mAppThread.asBinder());
1012 removeRequestedPss(mApp);
1013 synchronized(ActivityManagerService.this) {
1014 appDiedLocked(mApp, mPid, mAppThread);
1015 }
1016 }
1017 }
1018
1019 static final int SHOW_ERROR_MSG = 1;
1020 static final int SHOW_NOT_RESPONDING_MSG = 2;
1021 static final int SHOW_FACTORY_ERROR_MSG = 3;
1022 static final int UPDATE_CONFIGURATION_MSG = 4;
1023 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
1024 static final int WAIT_FOR_DEBUGGER_MSG = 6;
1025 static final int BROADCAST_INTENT_MSG = 7;
1026 static final int BROADCAST_TIMEOUT_MSG = 8;
1027 static final int PAUSE_TIMEOUT_MSG = 9;
1028 static final int IDLE_TIMEOUT_MSG = 10;
1029 static final int IDLE_NOW_MSG = 11;
1030 static final int SERVICE_TIMEOUT_MSG = 12;
1031 static final int UPDATE_TIME_ZONE = 13;
1032 static final int SHOW_UID_ERROR_MSG = 14;
1033 static final int IM_FEELING_LUCKY_MSG = 15;
1034 static final int LAUNCH_TIMEOUT_MSG = 16;
1035 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001036 static final int RESUME_TOP_ACTIVITY_MSG = 19;
1037 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001038 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001039 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001040 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001041 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
1042 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001043 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044
1045 AlertDialog mUidAlert;
1046
1047 final Handler mHandler = new Handler() {
1048 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001049 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 //}
1051
1052 public void handleMessage(Message msg) {
1053 switch (msg.what) {
1054 case SHOW_ERROR_MSG: {
1055 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 synchronized (ActivityManagerService.this) {
1057 ProcessRecord proc = (ProcessRecord)data.get("app");
1058 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001059 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 return;
1061 }
1062 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001063 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001064 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 d.show();
1066 proc.crashDialog = d;
1067 } else {
1068 // The device is asleep, so just pretend that the user
1069 // saw a crash dialog and hit "force quit".
1070 res.set(0);
1071 }
1072 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001073
1074 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 } break;
1076 case SHOW_NOT_RESPONDING_MSG: {
1077 synchronized (ActivityManagerService.this) {
1078 HashMap data = (HashMap) msg.obj;
1079 ProcessRecord proc = (ProcessRecord)data.get("app");
1080 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001081 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 return;
1083 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001084
1085 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1086 null, null, 0, null, null, null,
1087 false, false, MY_PID, Process.SYSTEM_UID);
1088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1090 mContext, proc, (HistoryRecord)data.get("activity"));
1091 d.show();
1092 proc.anrDialog = d;
1093 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001094
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001095 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001097 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1098 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1099 synchronized (ActivityManagerService.this) {
1100 ProcessRecord proc = (ProcessRecord) data.get("app");
1101 if (proc == null) {
1102 Slog.e(TAG, "App not found when showing strict mode dialog.");
1103 break;
1104 }
1105 if (proc.crashDialog != null) {
1106 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1107 return;
1108 }
1109 AppErrorResult res = (AppErrorResult) data.get("result");
1110 if (!mSleeping && !mShuttingDown) {
1111 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1112 d.show();
1113 proc.crashDialog = d;
1114 } else {
1115 // The device is asleep, so just pretend that the user
1116 // saw a crash dialog and hit "force quit".
1117 res.set(0);
1118 }
1119 }
1120 ensureBootCompleted();
1121 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 case SHOW_FACTORY_ERROR_MSG: {
1123 Dialog d = new FactoryErrorDialog(
1124 mContext, msg.getData().getCharSequence("msg"));
1125 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001126 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 } break;
1128 case UPDATE_CONFIGURATION_MSG: {
1129 final ContentResolver resolver = mContext.getContentResolver();
1130 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1131 } break;
1132 case GC_BACKGROUND_PROCESSES_MSG: {
1133 synchronized (ActivityManagerService.this) {
1134 performAppGcsIfAppropriateLocked();
1135 }
1136 } break;
1137 case WAIT_FOR_DEBUGGER_MSG: {
1138 synchronized (ActivityManagerService.this) {
1139 ProcessRecord app = (ProcessRecord)msg.obj;
1140 if (msg.arg1 != 0) {
1141 if (!app.waitedForDebugger) {
1142 Dialog d = new AppWaitingForDebuggerDialog(
1143 ActivityManagerService.this,
1144 mContext, app);
1145 app.waitDialog = d;
1146 app.waitedForDebugger = true;
1147 d.show();
1148 }
1149 } else {
1150 if (app.waitDialog != null) {
1151 app.waitDialog.dismiss();
1152 app.waitDialog = null;
1153 }
1154 }
1155 }
1156 } break;
1157 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001158 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 TAG, "Received BROADCAST_INTENT_MSG");
1160 processNextBroadcast(true);
1161 } break;
1162 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001163 if (mDidDexOpt) {
1164 mDidDexOpt = false;
1165 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1166 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1167 return;
1168 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001169 // Only process broadcast timeouts if the system is ready. That way
1170 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1171 // to do heavy lifting for system up
1172 if (mSystemReady) {
1173 broadcastTimeout();
1174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 } break;
1176 case PAUSE_TIMEOUT_MSG: {
1177 IBinder token = (IBinder)msg.obj;
1178 // We don't at this point know if the activity is fullscreen,
1179 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001180 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 activityPaused(token, null, true);
1182 } break;
1183 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001184 if (mDidDexOpt) {
1185 mDidDexOpt = false;
1186 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1187 nmsg.obj = msg.obj;
1188 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1189 return;
1190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 // We don't at this point know if the activity is fullscreen,
1192 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001193 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001194 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001195 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 } break;
1197 case DESTROY_TIMEOUT_MSG: {
1198 IBinder token = (IBinder)msg.obj;
1199 // We don't at this point know if the activity is fullscreen,
1200 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001201 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 activityDestroyed(token);
1203 } break;
1204 case IDLE_NOW_MSG: {
1205 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001206 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 } break;
1208 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001209 if (mDidDexOpt) {
1210 mDidDexOpt = false;
1211 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1212 nmsg.obj = msg.obj;
1213 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1214 return;
1215 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216 serviceTimeout((ProcessRecord)msg.obj);
1217 } break;
1218 case UPDATE_TIME_ZONE: {
1219 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001220 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1221 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 if (r.thread != null) {
1223 try {
1224 r.thread.updateTimeZone();
1225 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001226 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227 }
1228 }
1229 }
1230 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001231 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232 case SHOW_UID_ERROR_MSG: {
1233 // XXX This is a temporary dialog, no need to localize.
1234 AlertDialog d = new BaseErrorDialog(mContext);
1235 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1236 d.setCancelable(false);
1237 d.setTitle("System UIDs Inconsistent");
1238 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1239 d.setButton("I'm Feeling Lucky",
1240 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1241 mUidAlert = d;
1242 d.show();
1243 } break;
1244 case IM_FEELING_LUCKY_MSG: {
1245 if (mUidAlert != null) {
1246 mUidAlert.dismiss();
1247 mUidAlert = null;
1248 }
1249 } break;
1250 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001251 if (mDidDexOpt) {
1252 mDidDexOpt = false;
1253 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1254 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1255 return;
1256 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 synchronized (ActivityManagerService.this) {
1258 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001259 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 mLaunchingActivity.release();
1261 }
1262 }
1263 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264 case RESUME_TOP_ACTIVITY_MSG: {
1265 synchronized (ActivityManagerService.this) {
1266 resumeTopActivityLocked(null);
1267 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001268 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001269 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001270 if (mDidDexOpt) {
1271 mDidDexOpt = false;
1272 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1273 nmsg.obj = msg.obj;
1274 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1275 return;
1276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277 ProcessRecord app = (ProcessRecord)msg.obj;
1278 synchronized (ActivityManagerService.this) {
1279 processStartTimedOutLocked(app);
1280 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001281 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001282 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1283 synchronized (ActivityManagerService.this) {
1284 doPendingActivityLaunchesLocked(true);
1285 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001286 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001287 case KILL_APPLICATION_MSG: {
1288 synchronized (ActivityManagerService.this) {
1289 int uid = msg.arg1;
1290 boolean restart = (msg.arg2 == 1);
1291 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001292 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001293 }
1294 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001295 case FINALIZE_PENDING_INTENT_MSG: {
1296 ((PendingIntentRecord)msg.obj).completeFinalize();
1297 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001298 case POST_HEAVY_NOTIFICATION_MSG: {
1299 INotificationManager inm = NotificationManager.getService();
1300 if (inm == null) {
1301 return;
1302 }
1303
1304 HistoryRecord root = (HistoryRecord)msg.obj;
1305 ProcessRecord process = root.app;
1306 if (process == null) {
1307 return;
1308 }
1309
1310 try {
1311 Context context = mContext.createPackageContext(process.info.packageName, 0);
1312 String text = mContext.getString(R.string.heavy_weight_notification,
1313 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1314 Notification notification = new Notification();
1315 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1316 notification.when = 0;
1317 notification.flags = Notification.FLAG_ONGOING_EVENT;
1318 notification.tickerText = text;
1319 notification.defaults = 0; // please be quiet
1320 notification.sound = null;
1321 notification.vibrate = null;
1322 notification.setLatestEventInfo(context, text,
1323 mContext.getText(R.string.heavy_weight_notification_detail),
1324 PendingIntent.getActivity(mContext, 0, root.intent,
1325 PendingIntent.FLAG_CANCEL_CURRENT));
1326
1327 try {
1328 int[] outId = new int[1];
1329 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1330 notification, outId);
1331 } catch (RuntimeException e) {
1332 Slog.w(ActivityManagerService.TAG,
1333 "Error showing notification for heavy-weight app", e);
1334 } catch (RemoteException e) {
1335 }
1336 } catch (NameNotFoundException e) {
1337 Log.w(TAG, "Unable to create context for heavy notification", e);
1338 }
1339 } break;
1340 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1341 INotificationManager inm = NotificationManager.getService();
1342 if (inm == null) {
1343 return;
1344 }
1345 try {
1346 inm.cancelNotification("android",
1347 R.string.heavy_weight_notification);
1348 } catch (RuntimeException e) {
1349 Slog.w(ActivityManagerService.TAG,
1350 "Error canceling notification for service", e);
1351 } catch (RemoteException e) {
1352 }
1353 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354 }
1355 }
1356 };
1357
1358 public static void setSystemProcess() {
1359 try {
1360 ActivityManagerService m = mSelf;
1361
1362 ServiceManager.addService("activity", m);
1363 ServiceManager.addService("meminfo", new MemBinder(m));
1364 if (MONITOR_CPU_USAGE) {
1365 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 ServiceManager.addService("permission", new PermissionController(m));
1368
1369 ApplicationInfo info =
1370 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001371 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001372 mSystemThread.installSystemApplicationInfo(info);
1373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 synchronized (mSelf) {
1375 ProcessRecord app = mSelf.newProcessRecordLocked(
1376 mSystemThread.getApplicationThread(), info,
1377 info.processName);
1378 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001379 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 app.maxAdj = SYSTEM_ADJ;
1381 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1382 synchronized (mSelf.mPidsSelfLocked) {
1383 mSelf.mPidsSelfLocked.put(app.pid, app);
1384 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001385 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001386 }
1387 } catch (PackageManager.NameNotFoundException e) {
1388 throw new RuntimeException(
1389 "Unable to find android system package", e);
1390 }
1391 }
1392
1393 public void setWindowManager(WindowManagerService wm) {
1394 mWindowManager = wm;
1395 }
1396
1397 public static final Context main(int factoryTest) {
1398 AThread thr = new AThread();
1399 thr.start();
1400
1401 synchronized (thr) {
1402 while (thr.mService == null) {
1403 try {
1404 thr.wait();
1405 } catch (InterruptedException e) {
1406 }
1407 }
1408 }
1409
1410 ActivityManagerService m = thr.mService;
1411 mSelf = m;
1412 ActivityThread at = ActivityThread.systemMain();
1413 mSystemThread = at;
1414 Context context = at.getSystemContext();
1415 m.mContext = context;
1416 m.mFactoryTest = factoryTest;
1417 PowerManager pm =
1418 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1419 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1420 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1421 m.mLaunchingActivity.setReferenceCounted(false);
1422
1423 m.mBatteryStatsService.publish(context);
1424 m.mUsageStatsService.publish(context);
1425
1426 synchronized (thr) {
1427 thr.mReady = true;
1428 thr.notifyAll();
1429 }
1430
1431 m.startRunning(null, null, null, null);
1432
1433 return context;
1434 }
1435
1436 public static ActivityManagerService self() {
1437 return mSelf;
1438 }
1439
1440 static class AThread extends Thread {
1441 ActivityManagerService mService;
1442 boolean mReady = false;
1443
1444 public AThread() {
1445 super("ActivityManager");
1446 }
1447
1448 public void run() {
1449 Looper.prepare();
1450
1451 android.os.Process.setThreadPriority(
1452 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1453
1454 ActivityManagerService m = new ActivityManagerService();
1455
1456 synchronized (this) {
1457 mService = m;
1458 notifyAll();
1459 }
1460
1461 synchronized (this) {
1462 while (!mReady) {
1463 try {
1464 wait();
1465 } catch (InterruptedException e) {
1466 }
1467 }
1468 }
1469
1470 Looper.loop();
1471 }
1472 }
1473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 static class MemBinder extends Binder {
1475 ActivityManagerService mActivityManagerService;
1476 MemBinder(ActivityManagerService activityManagerService) {
1477 mActivityManagerService = activityManagerService;
1478 }
1479
1480 @Override
1481 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1482 ActivityManagerService service = mActivityManagerService;
1483 ArrayList<ProcessRecord> procs;
1484 synchronized (mActivityManagerService) {
1485 if (args != null && args.length > 0
1486 && args[0].charAt(0) != '-') {
1487 procs = new ArrayList<ProcessRecord>();
1488 int pid = -1;
1489 try {
1490 pid = Integer.parseInt(args[0]);
1491 } catch (NumberFormatException e) {
1492
1493 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001494 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1495 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 if (proc.pid == pid) {
1497 procs.add(proc);
1498 } else if (proc.processName.equals(args[0])) {
1499 procs.add(proc);
1500 }
1501 }
1502 if (procs.size() <= 0) {
1503 pw.println("No process found for: " + args[0]);
1504 return;
1505 }
1506 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001507 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 }
1509 }
1510 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1511 }
1512 }
1513
1514 static class CpuBinder extends Binder {
1515 ActivityManagerService mActivityManagerService;
1516 CpuBinder(ActivityManagerService activityManagerService) {
1517 mActivityManagerService = activityManagerService;
1518 }
1519
1520 @Override
1521 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1522 synchronized (mActivityManagerService.mProcessStatsThread) {
1523 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1524 }
1525 }
1526 }
1527
1528 private ActivityManagerService() {
1529 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1530 if (v != null && Integer.getInteger(v) != 0) {
1531 mSimpleProcessManagement = true;
1532 }
1533 v = System.getenv("ANDROID_DEBUG_APP");
1534 if (v != null) {
1535 mSimpleProcessManagement = true;
1536 }
1537
Joe Onorato8a9b2202010-02-26 18:56:32 -08001538 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 File dataDir = Environment.getDataDirectory();
1541 File systemDir = new File(dataDir, "system");
1542 systemDir.mkdirs();
1543 mBatteryStatsService = new BatteryStatsService(new File(
1544 systemDir, "batterystats.bin").toString());
1545 mBatteryStatsService.getActiveStatistics().readLocked();
1546 mBatteryStatsService.getActiveStatistics().writeLocked();
1547
1548 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001549 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550
Jack Palevichb90d28c2009-07-22 15:35:24 -07001551 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1552 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1553
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001554 mConfiguration.setToDefaults();
1555 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 mProcessStats.init();
1557
1558 // Add ourself to the Watchdog monitors.
1559 Watchdog.getInstance().addMonitor(this);
1560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 mProcessStatsThread = new Thread("ProcessStats") {
1562 public void run() {
1563 while (true) {
1564 try {
1565 try {
1566 synchronized(this) {
1567 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001568 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001570 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 // + ", write delay=" + nextWriteDelay);
1572 if (nextWriteDelay < nextCpuDelay) {
1573 nextCpuDelay = nextWriteDelay;
1574 }
1575 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001576 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 this.wait(nextCpuDelay);
1578 }
1579 }
1580 } catch (InterruptedException e) {
1581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 updateCpuStatsNow();
1583 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001584 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 }
1586 }
1587 }
1588 };
1589 mProcessStatsThread.start();
1590 }
1591
1592 @Override
1593 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1594 throws RemoteException {
1595 try {
1596 return super.onTransact(code, data, reply, flags);
1597 } catch (RuntimeException e) {
1598 // The activity manager only throws security exceptions, so let's
1599 // log all others.
1600 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001601 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 }
1603 throw e;
1604 }
1605 }
1606
1607 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001608 final long now = SystemClock.uptimeMillis();
1609 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1610 return;
1611 }
1612 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1613 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 mProcessStatsThread.notify();
1615 }
1616 }
1617 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 void updateCpuStatsNow() {
1620 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001621 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 final long now = SystemClock.uptimeMillis();
1623 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001626 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1627 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 haveNewCpuStats = true;
1629 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001630 //Slog.i(TAG, mProcessStats.printCurrentState());
1631 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 // + mProcessStats.getTotalCpuPercent() + "%");
1633
Joe Onorato8a9b2202010-02-26 18:56:32 -08001634 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 if ("true".equals(SystemProperties.get("events.cpu"))) {
1636 int user = mProcessStats.getLastUserTime();
1637 int system = mProcessStats.getLastSystemTime();
1638 int iowait = mProcessStats.getLastIoWaitTime();
1639 int irq = mProcessStats.getLastIrqTime();
1640 int softIrq = mProcessStats.getLastSoftIrqTime();
1641 int idle = mProcessStats.getLastIdleTime();
1642
1643 int total = user + system + iowait + irq + softIrq + idle;
1644 if (total == 0) total = 1;
1645
Doug Zongker2bec3d42009-12-04 12:52:44 -08001646 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 ((user+system+iowait+irq+softIrq) * 100) / total,
1648 (user * 100) / total,
1649 (system * 100) / total,
1650 (iowait * 100) / total,
1651 (irq * 100) / total,
1652 (softIrq * 100) / total);
1653 }
1654 }
1655
Amith Yamasanie43530a2009-08-21 13:11:37 -07001656 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001657 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001658 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 synchronized(mPidsSelfLocked) {
1660 if (haveNewCpuStats) {
1661 if (mBatteryStatsService.isOnBattery()) {
1662 final int N = mProcessStats.countWorkingStats();
1663 for (int i=0; i<N; i++) {
1664 ProcessStats.Stats st
1665 = mProcessStats.getWorkingStats(i);
1666 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1667 if (pr != null) {
1668 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1669 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001670 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001671 } else {
1672 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001673 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001674 if (ps != null) {
1675 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001676 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 }
1679 }
1680 }
1681 }
1682 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1685 mLastWriteTime = now;
1686 mBatteryStatsService.getActiveStatistics().writeLocked();
1687 }
1688 }
1689 }
1690 }
1691
1692 /**
1693 * Initialize the application bind args. These are passed to each
1694 * process when the bindApplication() IPC is sent to the process. They're
1695 * lazily setup to make sure the services are running when they're asked for.
1696 */
1697 private HashMap<String, IBinder> getCommonServicesLocked() {
1698 if (mAppBindArgs == null) {
1699 mAppBindArgs = new HashMap<String, IBinder>();
1700
1701 // Setup the application init args
1702 mAppBindArgs.put("package", ServiceManager.getService("package"));
1703 mAppBindArgs.put("window", ServiceManager.getService("window"));
1704 mAppBindArgs.put(Context.ALARM_SERVICE,
1705 ServiceManager.getService(Context.ALARM_SERVICE));
1706 }
1707 return mAppBindArgs;
1708 }
1709
1710 private final void setFocusedActivityLocked(HistoryRecord r) {
1711 if (mFocusedActivity != r) {
1712 mFocusedActivity = r;
1713 mWindowManager.setFocusedApp(r, true);
1714 }
1715 }
1716
Dianne Hackborn906497c2010-05-10 15:57:38 -07001717 private final void updateLruProcessInternalLocked(ProcessRecord app,
1718 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001720 int lrui = mLruProcesses.indexOf(app);
1721 if (lrui >= 0) mLruProcesses.remove(lrui);
1722
1723 int i = mLruProcesses.size()-1;
1724 int skipTop = 0;
1725
Dianne Hackborn906497c2010-05-10 15:57:38 -07001726 app.lruSeq = mLruSeq;
1727
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001728 // compute the new weight for this process.
1729 if (updateActivityTime) {
1730 app.lastActivityTime = SystemClock.uptimeMillis();
1731 }
1732 if (app.activities.size() > 0) {
1733 // If this process has activities, we more strongly want to keep
1734 // it around.
1735 app.lruWeight = app.lastActivityTime;
1736 } else if (app.pubProviders.size() > 0) {
1737 // If this process contains content providers, we want to keep
1738 // it a little more strongly.
1739 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1740 // Also don't let it kick out the first few "real" hidden processes.
1741 skipTop = MIN_HIDDEN_APPS;
1742 } else {
1743 // If this process doesn't have activities, we less strongly
1744 // want to keep it around, and generally want to avoid getting
1745 // in front of any very recently used activities.
1746 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1747 // Also don't let it kick out the first few "real" hidden processes.
1748 skipTop = MIN_HIDDEN_APPS;
1749 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001750
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001751 while (i >= 0) {
1752 ProcessRecord p = mLruProcesses.get(i);
1753 // If this app shouldn't be in front of the first N background
1754 // apps, then skip over that many that are currently hidden.
1755 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1756 skipTop--;
1757 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001758 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001759 mLruProcesses.add(i+1, app);
1760 break;
1761 }
1762 i--;
1763 }
1764 if (i < 0) {
1765 mLruProcesses.add(0, app);
1766 }
1767
Dianne Hackborn906497c2010-05-10 15:57:38 -07001768 // If the app is currently using a content provider or service,
1769 // bump those processes as well.
1770 if (app.connections.size() > 0) {
1771 for (ConnectionRecord cr : app.connections) {
1772 if (cr.binding != null && cr.binding.service != null
1773 && cr.binding.service.app != null
1774 && cr.binding.service.app.lruSeq != mLruSeq) {
1775 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1776 updateActivityTime, i+1);
1777 }
1778 }
1779 }
1780 if (app.conProviders.size() > 0) {
1781 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1782 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1783 updateLruProcessInternalLocked(cpr.app, oomAdj,
1784 updateActivityTime, i+1);
1785 }
1786 }
1787 }
1788
Joe Onorato8a9b2202010-02-26 18:56:32 -08001789 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001790 if (oomAdj) {
1791 updateOomAdjLocked();
1792 }
1793 }
1794
Dianne Hackborn906497c2010-05-10 15:57:38 -07001795 private final void updateLruProcessLocked(ProcessRecord app,
1796 boolean oomAdj, boolean updateActivityTime) {
1797 mLruSeq++;
1798 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1799 }
1800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 private final boolean updateLRUListLocked(HistoryRecord r) {
1802 final boolean hadit = mLRUActivities.remove(r);
1803 mLRUActivities.add(r);
1804 return hadit;
1805 }
1806
1807 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1808 int i = mHistory.size()-1;
1809 while (i >= 0) {
1810 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1811 if (!r.finishing && r != notTop) {
1812 return r;
1813 }
1814 i--;
1815 }
1816 return null;
1817 }
1818
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001819 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1820 int i = mHistory.size()-1;
1821 while (i >= 0) {
1822 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1823 if (!r.finishing && !r.delayedResume && r != notTop) {
1824 return r;
1825 }
1826 i--;
1827 }
1828 return null;
1829 }
1830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831 /**
1832 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001833 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001834 *
1835 * @param token If non-null, any history records matching this token will be skipped.
1836 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1837 *
1838 * @return Returns the HistoryRecord of the next activity on the stack.
1839 */
1840 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1841 int i = mHistory.size()-1;
1842 while (i >= 0) {
1843 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1844 // Note: the taskId check depends on real taskId fields being non-zero
1845 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1846 return r;
1847 }
1848 i--;
1849 }
1850 return null;
1851 }
1852
1853 private final ProcessRecord getProcessRecordLocked(
1854 String processName, int uid) {
1855 if (uid == Process.SYSTEM_UID) {
1856 // The system gets to run in any process. If there are multiple
1857 // processes with the same uid, just pick the first (this
1858 // should never happen).
1859 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1860 processName);
1861 return procs != null ? procs.valueAt(0) : null;
1862 }
1863 ProcessRecord proc = mProcessNames.get(processName, uid);
1864 return proc;
1865 }
1866
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001867 private void ensurePackageDexOpt(String packageName) {
1868 IPackageManager pm = ActivityThread.getPackageManager();
1869 try {
1870 if (pm.performDexOpt(packageName)) {
1871 mDidDexOpt = true;
1872 }
1873 } catch (RemoteException e) {
1874 }
1875 }
1876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 private boolean isNextTransitionForward() {
1878 int transit = mWindowManager.getPendingAppTransition();
1879 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1880 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1881 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1882 }
1883
1884 private final boolean realStartActivityLocked(HistoryRecord r,
1885 ProcessRecord app, boolean andResume, boolean checkConfig)
1886 throws RemoteException {
1887
1888 r.startFreezingScreenLocked(app, 0);
1889 mWindowManager.setAppVisibility(r, true);
1890
1891 // Have the window manager re-evaluate the orientation of
1892 // the screen based on the new activity order. Note that
1893 // as a result of this, it can call back into the activity
1894 // manager with a new orientation. We don't care about that,
1895 // because the activity is not currently running so we are
1896 // just restarting it anyway.
1897 if (checkConfig) {
1898 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001899 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001900 r.mayFreezeScreenLocked(app) ? r : null);
1901 updateConfigurationLocked(config, r);
1902 }
1903
1904 r.app = app;
1905
Joe Onorato8a9b2202010-02-26 18:56:32 -08001906 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001907
1908 int idx = app.activities.indexOf(r);
1909 if (idx < 0) {
1910 app.activities.add(r);
1911 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001912 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913
1914 try {
1915 if (app.thread == null) {
1916 throw new RemoteException();
1917 }
1918 List<ResultInfo> results = null;
1919 List<Intent> newIntents = null;
1920 if (andResume) {
1921 results = r.results;
1922 newIntents = r.newIntents;
1923 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001924 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001925 + " icicle=" + r.icicle
1926 + " with results=" + results + " newIntents=" + newIntents
1927 + " andResume=" + andResume);
1928 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001929 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 System.identityHashCode(r),
1931 r.task.taskId, r.shortComponentName);
1932 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001933 if (r.isHomeActivity) {
1934 mHomeProcess = app;
1935 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001936 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001938 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 r.info, r.icicle, results, newIntents, !andResume,
1940 isNextTransitionForward());
Dianne Hackborn860755f2010-06-03 18:47:52 -07001941
1942 if ((app.info.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
1943 // This may be a heavy-weight process! Note that the package
1944 // manager will ensure that only activity can run in the main
1945 // process of the .apk, which is the only thing that will be
1946 // considered heavy-weight.
1947 if (app.processName.equals(app.info.packageName)) {
1948 if (mHeavyWeightProcess != null && mHeavyWeightProcess != app) {
1949 Log.w(TAG, "Starting new heavy weight process " + app
1950 + " when already running " + mHeavyWeightProcess);
1951 }
1952 mHeavyWeightProcess = app;
1953 Message msg = mHandler.obtainMessage(POST_HEAVY_NOTIFICATION_MSG);
1954 msg.obj = r;
1955 mHandler.sendMessage(msg);
1956 }
1957 }
1958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001959 } catch (RemoteException e) {
1960 if (r.launchFailed) {
1961 // This is the second time we failed -- finish activity
1962 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001963 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001964 + r.intent.getComponent().flattenToShortString()
1965 + ", giving up", e);
1966 appDiedLocked(app, app.pid, app.thread);
1967 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1968 "2nd-crash");
1969 return false;
1970 }
1971
1972 // This is the first time we failed -- restart process and
1973 // retry.
1974 app.activities.remove(r);
1975 throw e;
1976 }
1977
1978 r.launchFailed = false;
1979 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001980 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001981 + " being launched, but already in LRU list");
1982 }
1983
1984 if (andResume) {
1985 // As part of the process of launching, ActivityThread also performs
1986 // a resume.
1987 r.state = ActivityState.RESUMED;
1988 r.icicle = null;
1989 r.haveState = false;
1990 r.stopped = false;
1991 mResumedActivity = r;
1992 r.task.touchActiveTime();
1993 completeResumeLocked(r);
1994 pauseIfSleepingLocked();
1995 } else {
1996 // This activity is not starting in the resumed state... which
1997 // should look like we asked it to pause+stop (but remain visible),
1998 // and it has done so and reported back the current icicle and
1999 // other state.
2000 r.state = ActivityState.STOPPED;
2001 r.stopped = true;
2002 }
2003
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002004 // Launch the new version setup screen if needed. We do this -after-
2005 // launching the initial activity (that is, home), so that it can have
2006 // a chance to initialize itself while in the background, making the
2007 // switch back to it faster and look better.
2008 startSetupActivityLocked();
2009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 return true;
2011 }
2012
2013 private final void startSpecificActivityLocked(HistoryRecord r,
2014 boolean andResume, boolean checkConfig) {
2015 // Is this activity's application already running?
2016 ProcessRecord app = getProcessRecordLocked(r.processName,
2017 r.info.applicationInfo.uid);
2018
2019 if (r.startTime == 0) {
2020 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002021 if (mInitialStartTime == 0) {
2022 mInitialStartTime = r.startTime;
2023 }
2024 } else if (mInitialStartTime == 0) {
2025 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 }
2027
2028 if (app != null && app.thread != null) {
2029 try {
2030 realStartActivityLocked(r, app, andResume, checkConfig);
2031 return;
2032 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002033 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002034 + r.intent.getComponent().flattenToShortString(), e);
2035 }
2036
2037 // If a dead object exception was thrown -- fall through to
2038 // restart the application.
2039 }
2040
2041 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002042 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 }
2044
2045 private final ProcessRecord startProcessLocked(String processName,
2046 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002047 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
2049 // We don't have to do anything more if:
2050 // (1) There is an existing application record; and
2051 // (2) The caller doesn't think it is dead, OR there is no thread
2052 // object attached to it so we know it couldn't have crashed; and
2053 // (3) There is a pid assigned to it, so it is either starting or
2054 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002055 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 + " app=" + app + " knownToBeDead=" + knownToBeDead
2057 + " thread=" + (app != null ? app.thread : null)
2058 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01002059 if (app != null && app.pid > 0) {
2060 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002061 // We already have the app running, or are waiting for it to
2062 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01002063 return app;
2064 } else {
2065 // An application record is attached to a previous process,
2066 // clean it up now.
2067 handleAppDiedLocked(app, true);
2068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 String hostingNameStr = hostingName != null
2072 ? hostingName.flattenToShortString() : null;
2073
2074 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
2075 // If we are in the background, then check to see if this process
2076 // is bad. If so, we will just silently fail.
2077 if (mBadProcesses.get(info.processName, info.uid) != null) {
2078 return null;
2079 }
2080 } else {
2081 // When the user is explicitly starting a process, then clear its
2082 // crash count so that we won't make it bad until they see at
2083 // least one crash dialog again, and make the process good again
2084 // if it had been bad.
2085 mProcessCrashTimes.remove(info.processName, info.uid);
2086 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002087 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002088 info.processName);
2089 mBadProcesses.remove(info.processName, info.uid);
2090 if (app != null) {
2091 app.bad = false;
2092 }
2093 }
2094 }
2095
2096 if (app == null) {
2097 app = newProcessRecordLocked(null, info, processName);
2098 mProcessNames.put(processName, info.uid, app);
2099 } else {
2100 // If this is a new package in the process, add the package to the list
2101 app.addPackage(info.packageName);
2102 }
2103
2104 // If the system is not ready yet, then hold off on starting this
2105 // process until it is.
2106 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002107 && !isAllowedWhileBooting(info)
2108 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 if (!mProcessesOnHold.contains(app)) {
2110 mProcessesOnHold.add(app);
2111 }
2112 return app;
2113 }
2114
2115 startProcessLocked(app, hostingType, hostingNameStr);
2116 return (app.pid != 0) ? app : null;
2117 }
2118
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002119 boolean isAllowedWhileBooting(ApplicationInfo ai) {
2120 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
2121 }
2122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002123 private final void startProcessLocked(ProcessRecord app,
2124 String hostingType, String hostingNameStr) {
2125 if (app.pid > 0 && app.pid != MY_PID) {
2126 synchronized (mPidsSelfLocked) {
2127 mPidsSelfLocked.remove(app.pid);
2128 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
2129 }
2130 app.pid = 0;
2131 }
2132
2133 mProcessesOnHold.remove(app);
2134
2135 updateCpuStats();
2136
2137 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
2138 mProcDeaths[0] = 0;
2139
2140 try {
2141 int uid = app.info.uid;
2142 int[] gids = null;
2143 try {
2144 gids = mContext.getPackageManager().getPackageGids(
2145 app.info.packageName);
2146 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002147 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 }
2149 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
2150 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2151 && mTopComponent != null
2152 && app.processName.equals(mTopComponent.getPackageName())) {
2153 uid = 0;
2154 }
2155 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
2156 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
2157 uid = 0;
2158 }
2159 }
2160 int debugFlags = 0;
2161 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
2162 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
2163 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08002164 // Run the app in safe mode if its manifest requests so or the
2165 // system is booted in safe mode.
2166 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
2167 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08002168 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
2169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
2171 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
2172 }
2173 if ("1".equals(SystemProperties.get("debug.assert"))) {
2174 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2175 }
2176 int pid = Process.start("android.app.ActivityThread",
2177 mSimpleProcessManagement ? app.processName : null, uid, uid,
2178 gids, debugFlags, null);
2179 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2180 synchronized (bs) {
2181 if (bs.isOnBattery()) {
2182 app.batteryStats.incStartsLocked();
2183 }
2184 }
2185
Doug Zongker2bec3d42009-12-04 12:52:44 -08002186 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187 app.processName, hostingType,
2188 hostingNameStr != null ? hostingNameStr : "");
2189
2190 if (app.persistent) {
2191 Watchdog.getInstance().processStarted(app, app.processName, pid);
2192 }
2193
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002194 StringBuilder buf = mStringBuilder;
2195 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 buf.append("Start proc ");
2197 buf.append(app.processName);
2198 buf.append(" for ");
2199 buf.append(hostingType);
2200 if (hostingNameStr != null) {
2201 buf.append(" ");
2202 buf.append(hostingNameStr);
2203 }
2204 buf.append(": pid=");
2205 buf.append(pid);
2206 buf.append(" uid=");
2207 buf.append(uid);
2208 buf.append(" gids={");
2209 if (gids != null) {
2210 for (int gi=0; gi<gids.length; gi++) {
2211 if (gi != 0) buf.append(", ");
2212 buf.append(gids[gi]);
2213
2214 }
2215 }
2216 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002217 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 if (pid == 0 || pid == MY_PID) {
2219 // Processes are being emulated with threads.
2220 app.pid = MY_PID;
2221 app.removed = false;
2222 mStartingProcesses.add(app);
2223 } else if (pid > 0) {
2224 app.pid = pid;
2225 app.removed = false;
2226 synchronized (mPidsSelfLocked) {
2227 this.mPidsSelfLocked.put(pid, app);
2228 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2229 msg.obj = app;
2230 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2231 }
2232 } else {
2233 app.pid = 0;
2234 RuntimeException e = new RuntimeException(
2235 "Failure starting process " + app.processName
2236 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002237 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002238 }
2239 } catch (RuntimeException e) {
2240 // XXX do better error recovery.
2241 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002242 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243 }
2244 }
2245
2246 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2247 if (mPausingActivity != null) {
2248 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002249 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 + mPausingActivity, e);
2251 }
2252 HistoryRecord prev = mResumedActivity;
2253 if (prev == null) {
2254 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002255 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 resumeTopActivityLocked(null);
2257 return;
2258 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002259 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002260 mResumedActivity = null;
2261 mPausingActivity = prev;
2262 mLastPausedActivity = prev;
2263 prev.state = ActivityState.PAUSING;
2264 prev.task.touchActiveTime();
2265
2266 updateCpuStats();
2267
2268 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002269 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002271 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 System.identityHashCode(prev),
2273 prev.shortComponentName);
2274 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2275 prev.configChangeFlags);
2276 updateUsageStats(prev, false);
2277 } catch (Exception e) {
2278 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002279 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 mPausingActivity = null;
2281 mLastPausedActivity = null;
2282 }
2283 } else {
2284 mPausingActivity = null;
2285 mLastPausedActivity = null;
2286 }
2287
2288 // If we are not going to sleep, we want to ensure the device is
2289 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002290 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002291 mLaunchingActivity.acquire();
2292 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2293 // To be safe, don't allow the wake lock to be held for too long.
2294 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2295 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2296 }
2297 }
2298
2299
2300 if (mPausingActivity != null) {
2301 // Have the window manager pause its key dispatching until the new
2302 // activity has started. If we're pausing the activity just because
2303 // the screen is being turned off and the UI is sleeping, don't interrupt
2304 // key dispatch; the same activity will pick it up again on wakeup.
2305 if (!uiSleeping) {
2306 prev.pauseKeyDispatchingLocked();
2307 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002308 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 }
2310
2311 // Schedule a pause timeout in case the app doesn't respond.
2312 // We don't give it much time because this directly impacts the
2313 // responsiveness seen by the user.
2314 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2315 msg.obj = prev;
2316 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002317 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 } else {
2319 // This activity failed to schedule the
2320 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002321 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002322 resumeTopActivityLocked(null);
2323 }
2324 }
2325
2326 private final void completePauseLocked() {
2327 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002328 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002329
2330 if (prev != null) {
2331 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002332 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002333 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2334 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002335 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002336 if (prev.waitingVisible) {
2337 prev.waitingVisible = false;
2338 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002339 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002340 TAG, "Complete pause, no longer waiting: " + prev);
2341 }
2342 if (prev.configDestroy) {
2343 // The previous is being paused because the configuration
2344 // is changing, which means it is actually stopping...
2345 // To juggle the fact that we are also starting a new
2346 // instance right now, we need to first completely stop
2347 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002348 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002349 destroyActivityLocked(prev, true);
2350 } else {
2351 mStoppingActivities.add(prev);
2352 if (mStoppingActivities.size() > 3) {
2353 // If we already have a few activities waiting to stop,
2354 // then give up on things going idle and start clearing
2355 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002356 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002357 Message msg = Message.obtain();
2358 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2359 mHandler.sendMessage(msg);
2360 }
2361 }
2362 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002363 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002364 prev = null;
2365 }
2366 mPausingActivity = null;
2367 }
2368
Dianne Hackborn55280a92009-05-07 15:53:46 -07002369 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 resumeTopActivityLocked(prev);
2371 } else {
2372 if (mGoingToSleep.isHeld()) {
2373 mGoingToSleep.release();
2374 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002375 if (mShuttingDown) {
2376 notifyAll();
2377 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002378 }
2379
2380 if (prev != null) {
2381 prev.resumeKeyDispatchingLocked();
2382 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002383
2384 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2385 long diff = 0;
2386 synchronized (mProcessStatsThread) {
2387 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2388 }
2389 if (diff > 0) {
2390 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2391 synchronized (bsi) {
2392 BatteryStatsImpl.Uid.Proc ps =
2393 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2394 prev.info.packageName);
2395 if (ps != null) {
2396 ps.addForegroundTimeLocked(diff);
2397 }
2398 }
2399 }
2400 }
2401 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 }
2403
2404 /**
2405 * Once we know that we have asked an application to put an activity in
2406 * the resumed state (either by launching it or explicitly telling it),
2407 * this function updates the rest of our state to match that fact.
2408 */
2409 private final void completeResumeLocked(HistoryRecord next) {
2410 next.idle = false;
2411 next.results = null;
2412 next.newIntents = null;
2413
2414 // schedule an idle timeout in case the app doesn't do it for us.
2415 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2416 msg.obj = next;
2417 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2418
2419 if (false) {
2420 // The activity was never told to pause, so just keep
2421 // things going as-is. To maintain our own state,
2422 // we need to emulate it coming back and saying it is
2423 // idle.
2424 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2425 msg.obj = next;
2426 mHandler.sendMessage(msg);
2427 }
2428
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002429 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002431 next.thumbnail = null;
2432 setFocusedActivityLocked(next);
2433 next.resumeKeyDispatchingLocked();
2434 ensureActivitiesVisibleLocked(null, 0);
2435 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002436 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002437
2438 // Mark the point when the activity is resuming
2439 // TODO: To be more accurate, the mark should be before the onCreate,
2440 // not after the onResume. But for subsequent starts, onResume is fine.
2441 if (next.app != null) {
2442 synchronized (mProcessStatsThread) {
2443 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2444 }
2445 } else {
2446 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002448 }
2449
2450 /**
2451 * Make sure that all activities that need to be visible (that is, they
2452 * currently can be seen by the user) actually are.
2453 */
2454 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2455 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002456 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002457 TAG, "ensureActivitiesVisible behind " + top
2458 + " configChanges=0x" + Integer.toHexString(configChanges));
2459
2460 // If the top activity is not fullscreen, then we need to
2461 // make sure any activities under it are now visible.
2462 final int count = mHistory.size();
2463 int i = count-1;
2464 while (mHistory.get(i) != top) {
2465 i--;
2466 }
2467 HistoryRecord r;
2468 boolean behindFullscreen = false;
2469 for (; i>=0; i--) {
2470 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002471 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002472 TAG, "Make visible? " + r + " finishing=" + r.finishing
2473 + " state=" + r.state);
2474 if (r.finishing) {
2475 continue;
2476 }
2477
2478 final boolean doThisProcess = onlyThisProcess == null
2479 || onlyThisProcess.equals(r.processName);
2480
2481 // First: if this is not the current activity being started, make
2482 // sure it matches the current configuration.
2483 if (r != starting && doThisProcess) {
2484 ensureActivityConfigurationLocked(r, 0);
2485 }
2486
2487 if (r.app == null || r.app.thread == null) {
2488 if (onlyThisProcess == null
2489 || onlyThisProcess.equals(r.processName)) {
2490 // This activity needs to be visible, but isn't even
2491 // running... get it started, but don't resume it
2492 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002493 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002494 TAG, "Start and freeze screen for " + r);
2495 if (r != starting) {
2496 r.startFreezingScreenLocked(r.app, configChanges);
2497 }
2498 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002499 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 TAG, "Starting and making visible: " + r);
2501 mWindowManager.setAppVisibility(r, true);
2502 }
2503 if (r != starting) {
2504 startSpecificActivityLocked(r, false, false);
2505 }
2506 }
2507
2508 } else if (r.visible) {
2509 // If this activity is already visible, then there is nothing
2510 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002511 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512 TAG, "Skipping: already visible at " + r);
2513 r.stopFreezingScreenLocked(false);
2514
2515 } else if (onlyThisProcess == null) {
2516 // This activity is not currently visible, but is running.
2517 // Tell it to become visible.
2518 r.visible = true;
2519 if (r.state != ActivityState.RESUMED && r != starting) {
2520 // If this activity is paused, tell it
2521 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002522 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 TAG, "Making visible and scheduling visibility: " + r);
2524 try {
2525 mWindowManager.setAppVisibility(r, true);
2526 r.app.thread.scheduleWindowVisibility(r, true);
2527 r.stopFreezingScreenLocked(false);
2528 } catch (Exception e) {
2529 // Just skip on any failure; we'll make it
2530 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002531 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 + r.intent.getComponent(), e);
2533 }
2534 }
2535 }
2536
2537 // Aggregate current change flags.
2538 configChanges |= r.configChangeFlags;
2539
2540 if (r.fullscreen) {
2541 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002542 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002543 TAG, "Stopping: fullscreen at " + r);
2544 behindFullscreen = true;
2545 i--;
2546 break;
2547 }
2548 }
2549
2550 // Now for any activities that aren't visible to the user, make
2551 // sure they no longer are keeping the screen frozen.
2552 while (i >= 0) {
2553 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002554 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2556 + " state=" + r.state
2557 + " behindFullscreen=" + behindFullscreen);
2558 if (!r.finishing) {
2559 if (behindFullscreen) {
2560 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002561 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 TAG, "Making invisible: " + r);
2563 r.visible = false;
2564 try {
2565 mWindowManager.setAppVisibility(r, false);
2566 if ((r.state == ActivityState.STOPPING
2567 || r.state == ActivityState.STOPPED)
2568 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002569 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 TAG, "Scheduling invisibility: " + r);
2571 r.app.thread.scheduleWindowVisibility(r, false);
2572 }
2573 } catch (Exception e) {
2574 // Just skip on any failure; we'll make it
2575 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002576 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002577 + r.intent.getComponent(), e);
2578 }
2579 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002580 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581 TAG, "Already invisible: " + r);
2582 }
2583 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002584 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 TAG, "Now behindFullscreen: " + r);
2586 behindFullscreen = true;
2587 }
2588 }
2589 i--;
2590 }
2591 }
2592
2593 /**
2594 * Version of ensureActivitiesVisible that can easily be called anywhere.
2595 */
2596 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2597 int configChanges) {
2598 HistoryRecord r = topRunningActivityLocked(null);
2599 if (r != null) {
2600 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2601 }
2602 }
2603
2604 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2605 if (resumed) {
2606 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2607 } else {
2608 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2609 }
2610 }
2611
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002612 private boolean startHomeActivityLocked() {
2613 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2614 && mTopAction == null) {
2615 // We are running in factory test mode, but unable to find
2616 // the factory test app, so just sit around displaying the
2617 // error message and don't try to start anything.
2618 return false;
2619 }
2620 Intent intent = new Intent(
2621 mTopAction,
2622 mTopData != null ? Uri.parse(mTopData) : null);
2623 intent.setComponent(mTopComponent);
2624 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2625 intent.addCategory(Intent.CATEGORY_HOME);
2626 }
2627 ActivityInfo aInfo =
2628 intent.resolveActivityInfo(mContext.getPackageManager(),
2629 STOCK_PM_FLAGS);
2630 if (aInfo != null) {
2631 intent.setComponent(new ComponentName(
2632 aInfo.applicationInfo.packageName, aInfo.name));
2633 // Don't do this if the home app is currently being
2634 // instrumented.
2635 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2636 aInfo.applicationInfo.uid);
2637 if (app == null || app.instrumentationClass == null) {
2638 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2639 startActivityLocked(null, intent, null, null, 0, aInfo,
2640 null, null, 0, 0, 0, false, false);
2641 }
2642 }
2643
2644
2645 return true;
2646 }
2647
2648 /**
2649 * Starts the "new version setup screen" if appropriate.
2650 */
2651 private void startSetupActivityLocked() {
2652 // Only do this once per boot.
2653 if (mCheckedForSetup) {
2654 return;
2655 }
2656
2657 // We will show this screen if the current one is a different
2658 // version than the last one shown, and we are not running in
2659 // low-level factory test mode.
2660 final ContentResolver resolver = mContext.getContentResolver();
2661 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2662 Settings.Secure.getInt(resolver,
2663 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2664 mCheckedForSetup = true;
2665
2666 // See if we should be showing the platform update setup UI.
2667 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2668 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2669 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2670
2671 // We don't allow third party apps to replace this.
2672 ResolveInfo ri = null;
2673 for (int i=0; ris != null && i<ris.size(); i++) {
2674 if ((ris.get(i).activityInfo.applicationInfo.flags
2675 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2676 ri = ris.get(i);
2677 break;
2678 }
2679 }
2680
2681 if (ri != null) {
2682 String vers = ri.activityInfo.metaData != null
2683 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2684 : null;
2685 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2686 vers = ri.activityInfo.applicationInfo.metaData.getString(
2687 Intent.METADATA_SETUP_VERSION);
2688 }
2689 String lastVers = Settings.Secure.getString(
2690 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2691 if (vers != null && !vers.equals(lastVers)) {
2692 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2693 intent.setComponent(new ComponentName(
2694 ri.activityInfo.packageName, ri.activityInfo.name));
2695 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2696 null, null, 0, 0, 0, false, false);
2697 }
2698 }
2699 }
2700 }
2701
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002702 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002703 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002704
2705 final int identHash = System.identityHashCode(r);
2706 updateUsageStats(r, true);
2707
2708 int i = mWatchers.beginBroadcast();
2709 while (i > 0) {
2710 i--;
2711 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2712 if (w != null) {
2713 try {
2714 w.activityResuming(identHash);
2715 } catch (RemoteException e) {
2716 }
2717 }
2718 }
2719 mWatchers.finishBroadcast();
2720 }
2721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 /**
2723 * Ensure that the top activity in the stack is resumed.
2724 *
2725 * @param prev The previously resumed activity, for when in the process
2726 * of pausing; can be null to call from elsewhere.
2727 *
2728 * @return Returns true if something is being resumed, or false if
2729 * nothing happened.
2730 */
2731 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2732 // Find the first activity that is not finishing.
2733 HistoryRecord next = topRunningActivityLocked(null);
2734
2735 // Remember how we'll process this pause/resume situation, and ensure
2736 // that the state is reset however we wind up proceeding.
2737 final boolean userLeaving = mUserLeaving;
2738 mUserLeaving = false;
2739
2740 if (next == null) {
2741 // There are no more activities! Let's just start up the
2742 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002743 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744 }
2745
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002746 next.delayedResume = false;
2747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 // If the top activity is the resumed one, nothing to do.
2749 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2750 // Make sure we have executed any pending transitions, since there
2751 // should be nothing left to do at this point.
2752 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002753 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002754 return false;
2755 }
2756
2757 // If we are sleeping, and there is no resumed activity, and the top
2758 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002759 if ((mSleeping || mShuttingDown)
2760 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761 // Make sure we have executed any pending transitions, since there
2762 // should be nothing left to do at this point.
2763 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002764 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 return false;
2766 }
2767
2768 // The activity may be waiting for stop, but that is no longer
2769 // appropriate for it.
2770 mStoppingActivities.remove(next);
2771 mWaitingVisibleActivities.remove(next);
2772
Joe Onorato8a9b2202010-02-26 18:56:32 -08002773 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002774
2775 // If we are currently pausing an activity, then don't do anything
2776 // until that is done.
2777 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002778 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 return false;
2780 }
2781
2782 // We need to start pausing the current activity so the top one
2783 // can be resumed...
2784 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002785 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 startPausingLocked(userLeaving, false);
2787 return true;
2788 }
2789
2790 if (prev != null && prev != next) {
2791 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2792 prev.waitingVisible = true;
2793 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002794 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 TAG, "Resuming top, waiting visible to hide: " + prev);
2796 } else {
2797 // The next activity is already visible, so hide the previous
2798 // activity's windows right now so we can show the new one ASAP.
2799 // We only do this if the previous is finishing, which should mean
2800 // it is on top of the one being resumed so hiding it quickly
2801 // is good. Otherwise, we want to do the normal route of allowing
2802 // the resumed activity to be shown so we can decide if the
2803 // previous should actually be hidden depending on whether the
2804 // new one is found to be full-screen or not.
2805 if (prev.finishing) {
2806 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002807 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 + prev + ", waitingVisible="
2809 + (prev != null ? prev.waitingVisible : null)
2810 + ", nowVisible=" + next.nowVisible);
2811 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002812 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813 + prev + ", waitingVisible="
2814 + (prev != null ? prev.waitingVisible : null)
2815 + ", nowVisible=" + next.nowVisible);
2816 }
2817 }
2818 }
2819
2820 // We are starting up the next activity, so tell the window manager
2821 // that the previous one will be hidden soon. This way it can know
2822 // to ignore it when computing the desired screen orientation.
2823 if (prev != null) {
2824 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002825 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002827 if (mNoAnimActivities.contains(prev)) {
2828 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2829 } else {
2830 mWindowManager.prepareAppTransition(prev.task == next.task
2831 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2832 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2833 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002834 mWindowManager.setAppWillBeHidden(prev);
2835 mWindowManager.setAppVisibility(prev, false);
2836 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002837 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002838 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002839 if (mNoAnimActivities.contains(next)) {
2840 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2841 } else {
2842 mWindowManager.prepareAppTransition(prev.task == next.task
2843 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2844 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002846 }
2847 if (false) {
2848 mWindowManager.setAppWillBeHidden(prev);
2849 mWindowManager.setAppVisibility(prev, false);
2850 }
2851 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002852 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002853 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002854 if (mNoAnimActivities.contains(next)) {
2855 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2856 } else {
2857 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 }
2860
2861 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002862 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863
2864 // This activity is now becoming visible.
2865 mWindowManager.setAppVisibility(next, true);
2866
2867 HistoryRecord lastResumedActivity = mResumedActivity;
2868 ActivityState lastState = next.state;
2869
2870 updateCpuStats();
2871
2872 next.state = ActivityState.RESUMED;
2873 mResumedActivity = next;
2874 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002875 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002876 updateLRUListLocked(next);
2877
2878 // Have the window manager re-evaluate the orientation of
2879 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002880 boolean updated;
2881 synchronized (this) {
2882 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2883 mConfiguration,
2884 next.mayFreezeScreenLocked(next.app) ? next : null);
2885 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002886 next.frozenBeforeDestroy = true;
2887 }
2888 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002889 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002890 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002891 // The configuration update wasn't able to keep the existing
2892 // instance of the activity, and instead started a new one.
2893 // We should be all done, but let's just make sure our activity
2894 // is still at the top and schedule another run if something
2895 // weird happened.
2896 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002897 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002898 "Activity config changed during resume: " + next
2899 + ", new next: " + nextNext);
2900 if (nextNext != next) {
2901 // Do over!
2902 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2903 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002904 setFocusedActivityLocked(next);
2905 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002906 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002907 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 return true;
2909 }
2910
2911 try {
2912 // Deliver all pending results.
2913 ArrayList a = next.results;
2914 if (a != null) {
2915 final int N = a.size();
2916 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002917 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002918 TAG, "Delivering results to " + next
2919 + ": " + a);
2920 next.app.thread.scheduleSendResult(next, a);
2921 }
2922 }
2923
2924 if (next.newIntents != null) {
2925 next.app.thread.scheduleNewIntent(next.newIntents, next);
2926 }
2927
Doug Zongker2bec3d42009-12-04 12:52:44 -08002928 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 System.identityHashCode(next),
2930 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002931
2932 next.app.thread.scheduleResumeActivity(next,
2933 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 pauseIfSleepingLocked();
2936
2937 } catch (Exception e) {
2938 // Whoops, need to restart this activity!
2939 next.state = lastState;
2940 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002941 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 if (!next.hasBeenLaunched) {
2943 next.hasBeenLaunched = true;
2944 } else {
2945 if (SHOW_APP_STARTING_ICON) {
2946 mWindowManager.setAppStartingWindow(
2947 next, next.packageName, next.theme,
2948 next.nonLocalizedLabel,
2949 next.labelRes, next.icon, null, true);
2950 }
2951 }
2952 startSpecificActivityLocked(next, true, false);
2953 return true;
2954 }
2955
2956 // From this point on, if something goes wrong there is no way
2957 // to recover the activity.
2958 try {
2959 next.visible = true;
2960 completeResumeLocked(next);
2961 } catch (Exception e) {
2962 // If any exception gets thrown, toss away this
2963 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002964 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002965 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2966 "resume-exception");
2967 return true;
2968 }
2969
2970 // Didn't need to use the icicle, and it is now out of date.
2971 next.icicle = null;
2972 next.haveState = false;
2973 next.stopped = false;
2974
2975 } else {
2976 // Whoops, need to restart this activity!
2977 if (!next.hasBeenLaunched) {
2978 next.hasBeenLaunched = true;
2979 } else {
2980 if (SHOW_APP_STARTING_ICON) {
2981 mWindowManager.setAppStartingWindow(
2982 next, next.packageName, next.theme,
2983 next.nonLocalizedLabel,
2984 next.labelRes, next.icon, null, true);
2985 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002986 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 }
2988 startSpecificActivityLocked(next, true, true);
2989 }
2990
2991 return true;
2992 }
2993
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002994 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2995 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002996 final int NH = mHistory.size();
2997
2998 int addPos = -1;
2999
3000 if (!newTask) {
3001 // If starting in an existing task, find where that is...
3002 HistoryRecord next = null;
3003 boolean startIt = true;
3004 for (int i = NH-1; i >= 0; i--) {
3005 HistoryRecord p = (HistoryRecord)mHistory.get(i);
3006 if (p.finishing) {
3007 continue;
3008 }
3009 if (p.task == r.task) {
3010 // Here it is! Now, if this is not yet visible to the
3011 // user, then just add it without starting; it will
3012 // get started when the user navigates back to it.
3013 addPos = i+1;
3014 if (!startIt) {
3015 mHistory.add(addPos, r);
3016 r.inHistory = true;
3017 r.task.numActivities++;
3018 mWindowManager.addAppToken(addPos, r, r.task.taskId,
3019 r.info.screenOrientation, r.fullscreen);
3020 if (VALIDATE_TOKENS) {
3021 mWindowManager.validateAppTokens(mHistory);
3022 }
3023 return;
3024 }
3025 break;
3026 }
3027 if (p.fullscreen) {
3028 startIt = false;
3029 }
3030 next = p;
3031 }
3032 }
3033
3034 // Place a new activity at top of stack, so it is next to interact
3035 // with the user.
3036 if (addPos < 0) {
3037 addPos = mHistory.size();
3038 }
3039
3040 // If we are not placing the new activity frontmost, we do not want
3041 // to deliver the onUserLeaving callback to the actual frontmost
3042 // activity
3043 if (addPos < NH) {
3044 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003045 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 }
3047
3048 // Slot the activity into the history stack and proceed
3049 mHistory.add(addPos, r);
3050 r.inHistory = true;
3051 r.frontOfTask = newTask;
3052 r.task.numActivities++;
3053 if (NH > 0) {
3054 // We want to show the starting preview window if we are
3055 // switching to a new task, or the next activity's process is
3056 // not currently running.
3057 boolean showStartingIcon = newTask;
3058 ProcessRecord proc = r.app;
3059 if (proc == null) {
3060 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
3061 }
3062 if (proc == null || proc.thread == null) {
3063 showStartingIcon = true;
3064 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003065 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003067 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3068 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
3069 mNoAnimActivities.add(r);
3070 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3071 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
3072 mNoAnimActivities.remove(r);
3073 } else {
3074 mWindowManager.prepareAppTransition(newTask
3075 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
3076 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
3077 mNoAnimActivities.remove(r);
3078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003079 mWindowManager.addAppToken(
3080 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
3081 boolean doShow = true;
3082 if (newTask) {
3083 // Even though this activity is starting fresh, we still need
3084 // to reset it to make sure we apply affinities to move any
3085 // existing activities from other tasks in to it.
3086 // If the caller has requested that the target task be
3087 // reset, then do so.
3088 if ((r.intent.getFlags()
3089 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3090 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003091 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003092 }
3093 }
3094 if (SHOW_APP_STARTING_ICON && doShow) {
3095 // Figure out if we are transitioning from another activity that is
3096 // "has the same starting icon" as the next one. This allows the
3097 // window manager to keep the previous window it had previously
3098 // created, if it still had one.
3099 HistoryRecord prev = mResumedActivity;
3100 if (prev != null) {
3101 // We don't want to reuse the previous starting preview if:
3102 // (1) The current activity is in a different task.
3103 if (prev.task != r.task) prev = null;
3104 // (2) The current activity is already displayed.
3105 else if (prev.nowVisible) prev = null;
3106 }
3107 mWindowManager.setAppStartingWindow(
3108 r, r.packageName, r.theme, r.nonLocalizedLabel,
3109 r.labelRes, r.icon, prev, showStartingIcon);
3110 }
3111 } else {
3112 // If this is the first activity, don't do any fancy animations,
3113 // because there is nothing for it to animate on top of.
3114 mWindowManager.addAppToken(addPos, r, r.task.taskId,
3115 r.info.screenOrientation, r.fullscreen);
3116 }
3117 if (VALIDATE_TOKENS) {
3118 mWindowManager.validateAppTokens(mHistory);
3119 }
3120
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003121 if (doResume) {
3122 resumeTopActivityLocked(null);
3123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003124 }
3125
3126 /**
3127 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003128 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
3129 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003130 * an instance of that activity in the stack and, if found, finish all
3131 * activities on top of it and return the instance.
3132 *
3133 * @param newR Description of the new activity being started.
3134 * @return Returns the old activity that should be continue to be used,
3135 * or null if none was found.
3136 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003137 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003138 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003139 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003140
3141 // First find the requested task.
3142 while (i > 0) {
3143 i--;
3144 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3145 if (r.task.taskId == taskId) {
3146 i++;
3147 break;
3148 }
3149 }
3150
3151 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003152 while (i > 0) {
3153 i--;
3154 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3155 if (r.finishing) {
3156 continue;
3157 }
3158 if (r.task.taskId != taskId) {
3159 return null;
3160 }
3161 if (r.realActivity.equals(newR.realActivity)) {
3162 // Here it is! Now finish everything in front...
3163 HistoryRecord ret = r;
3164 if (doClear) {
3165 while (i < (mHistory.size()-1)) {
3166 i++;
3167 r = (HistoryRecord)mHistory.get(i);
3168 if (r.finishing) {
3169 continue;
3170 }
3171 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3172 null, "clear")) {
3173 i--;
3174 }
3175 }
3176 }
3177
3178 // Finally, if this is a normal launch mode (that is, not
3179 // expecting onNewIntent()), then we will finish the current
3180 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003181 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
3182 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003183 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003184 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003185 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07003186 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 null, "clear");
3188 }
3189 return null;
3190 }
3191 }
3192
3193 return ret;
3194 }
3195 }
3196
3197 return null;
3198 }
3199
3200 /**
3201 * Find the activity in the history stack within the given task. Returns
3202 * the index within the history at which it's found, or < 0 if not found.
3203 */
3204 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3205 int i = mHistory.size();
3206 while (i > 0) {
3207 i--;
3208 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3209 if (candidate.task.taskId != task) {
3210 break;
3211 }
3212 if (candidate.realActivity.equals(r.realActivity)) {
3213 return i;
3214 }
3215 }
3216
3217 return -1;
3218 }
3219
3220 /**
3221 * Reorder the history stack so that the activity at the given index is
3222 * brought to the front.
3223 */
3224 private final HistoryRecord moveActivityToFrontLocked(int where) {
3225 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3226 int top = mHistory.size();
3227 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3228 mHistory.add(top, newTop);
3229 oldTop.frontOfTask = false;
3230 newTop.frontOfTask = true;
3231 return newTop;
3232 }
3233
3234 /**
3235 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3236 * method will be called at the proper time.
3237 */
3238 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3239 boolean sent = false;
3240 if (r.state == ActivityState.RESUMED
3241 && r.app != null && r.app.thread != null) {
3242 try {
3243 ArrayList<Intent> ar = new ArrayList<Intent>();
3244 ar.add(new Intent(intent));
3245 r.app.thread.scheduleNewIntent(ar, r);
3246 sent = true;
3247 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003248 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 }
3250 }
3251 if (!sent) {
3252 r.addNewIntentLocked(new Intent(intent));
3253 }
3254 }
3255
3256 private final void logStartActivity(int tag, HistoryRecord r,
3257 TaskRecord task) {
3258 EventLog.writeEvent(tag,
3259 System.identityHashCode(r), task.taskId,
3260 r.shortComponentName, r.intent.getAction(),
3261 r.intent.getType(), r.intent.getDataString(),
3262 r.intent.getFlags());
3263 }
3264
3265 private final int startActivityLocked(IApplicationThread caller,
3266 Intent intent, String resolvedType,
3267 Uri[] grantedUriPermissions,
3268 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3269 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003270 int callingPid, int callingUid, boolean onlyIfNeeded,
3271 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003272 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003273
3274 HistoryRecord sourceRecord = null;
3275 HistoryRecord resultRecord = null;
3276 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003277 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003278 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003279 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3280 if (index >= 0) {
3281 sourceRecord = (HistoryRecord)mHistory.get(index);
3282 if (requestCode >= 0 && !sourceRecord.finishing) {
3283 resultRecord = sourceRecord;
3284 }
3285 }
3286 }
3287
3288 int launchFlags = intent.getFlags();
3289
3290 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3291 && sourceRecord != null) {
3292 // Transfer the result target from the source activity to the new
3293 // one being started, including any failures.
3294 if (requestCode >= 0) {
3295 return START_FORWARD_AND_REQUEST_CONFLICT;
3296 }
3297 resultRecord = sourceRecord.resultTo;
3298 resultWho = sourceRecord.resultWho;
3299 requestCode = sourceRecord.requestCode;
3300 sourceRecord.resultTo = null;
3301 if (resultRecord != null) {
3302 resultRecord.removeResultsLocked(
3303 sourceRecord, resultWho, requestCode);
3304 }
3305 }
3306
3307 int err = START_SUCCESS;
3308
3309 if (intent.getComponent() == null) {
3310 // We couldn't find a class that can handle the given Intent.
3311 // That's the end of that!
3312 err = START_INTENT_NOT_RESOLVED;
3313 }
3314
3315 if (err == START_SUCCESS && aInfo == null) {
3316 // We couldn't find the specific class specified in the Intent.
3317 // Also the end of the line.
3318 err = START_CLASS_NOT_FOUND;
3319 }
3320
3321 ProcessRecord callerApp = null;
3322 if (err == START_SUCCESS && caller != null) {
3323 callerApp = getRecordForAppLocked(caller);
3324 if (callerApp != null) {
3325 callingPid = callerApp.pid;
3326 callingUid = callerApp.info.uid;
3327 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003328 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 + " (pid=" + callingPid + ") when starting: "
3330 + intent.toString());
3331 err = START_PERMISSION_DENIED;
3332 }
3333 }
3334
3335 if (err != START_SUCCESS) {
3336 if (resultRecord != null) {
3337 sendActivityResultLocked(-1,
3338 resultRecord, resultWho, requestCode,
3339 Activity.RESULT_CANCELED, null);
3340 }
3341 return err;
3342 }
3343
3344 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3345 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3346 if (perm != PackageManager.PERMISSION_GRANTED) {
3347 if (resultRecord != null) {
3348 sendActivityResultLocked(-1,
3349 resultRecord, resultWho, requestCode,
3350 Activity.RESULT_CANCELED, null);
3351 }
3352 String msg = "Permission Denial: starting " + intent.toString()
3353 + " from " + callerApp + " (pid=" + callingPid
3354 + ", uid=" + callingUid + ")"
3355 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003356 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357 throw new SecurityException(msg);
3358 }
3359
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003360 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003361 boolean abort = false;
3362 try {
3363 // The Intent we give to the watcher has the extra data
3364 // stripped off, since it can contain private information.
3365 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003366 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 aInfo.applicationInfo.packageName);
3368 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003369 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 }
3371
3372 if (abort) {
3373 if (resultRecord != null) {
3374 sendActivityResultLocked(-1,
3375 resultRecord, resultWho, requestCode,
3376 Activity.RESULT_CANCELED, null);
3377 }
3378 // We pretend to the caller that it was really started, but
3379 // they will just get a cancel result.
3380 return START_SUCCESS;
3381 }
3382 }
3383
3384 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3385 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003386 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003387
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003388 if (mResumedActivity == null
3389 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3390 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3391 PendingActivityLaunch pal = new PendingActivityLaunch();
3392 pal.r = r;
3393 pal.sourceRecord = sourceRecord;
3394 pal.grantedUriPermissions = grantedUriPermissions;
3395 pal.grantedMode = grantedMode;
3396 pal.onlyIfNeeded = onlyIfNeeded;
3397 mPendingActivityLaunches.add(pal);
3398 return START_SWITCHES_CANCELED;
3399 }
3400 }
3401
3402 if (mDidAppSwitch) {
3403 // This is the second allowed switch since we stopped switches,
3404 // so now just generally allow switches. Use case: user presses
3405 // home (switches disabled, switch to home, mDidAppSwitch now true);
3406 // user taps a home icon (coming from home so allowed, we hit here
3407 // and now allow anyone to switch again).
3408 mAppSwitchesAllowedTime = 0;
3409 } else {
3410 mDidAppSwitch = true;
3411 }
3412
3413 doPendingActivityLaunchesLocked(false);
3414
3415 return startActivityUncheckedLocked(r, sourceRecord,
3416 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3417 }
3418
3419 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3420 final int N = mPendingActivityLaunches.size();
3421 if (N <= 0) {
3422 return;
3423 }
3424 for (int i=0; i<N; i++) {
3425 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3426 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3427 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3428 doResume && i == (N-1));
3429 }
3430 mPendingActivityLaunches.clear();
3431 }
3432
3433 private final int startActivityUncheckedLocked(HistoryRecord r,
3434 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3435 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3436 final Intent intent = r.intent;
3437 final int callingUid = r.launchedFromUid;
3438
3439 int launchFlags = intent.getFlags();
3440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 // We'll invoke onUserLeaving before onPause only if the launching
3442 // activity did not explicitly state that this is an automated launch.
3443 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003444 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003445 "startActivity() => mUserLeaving=" + mUserLeaving);
3446
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003447 // If the caller has asked not to resume at this point, we make note
3448 // of this in the record so that we can skip it when trying to find
3449 // the top running activity.
3450 if (!doResume) {
3451 r.delayedResume = true;
3452 }
3453
3454 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3455 != 0 ? r : null;
3456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 // If the onlyIfNeeded flag is set, then we can do this if the activity
3458 // being launched is the same as the one making the call... or, as
3459 // a special case, if we do not know the caller then we count the
3460 // current top activity as the caller.
3461 if (onlyIfNeeded) {
3462 HistoryRecord checkedCaller = sourceRecord;
3463 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003464 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003465 }
3466 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3467 // Caller is not the same as launcher, so always needed.
3468 onlyIfNeeded = false;
3469 }
3470 }
3471
3472 if (grantedUriPermissions != null && callingUid > 0) {
3473 for (int i=0; i<grantedUriPermissions.length; i++) {
3474 grantUriPermissionLocked(callingUid, r.packageName,
3475 grantedUriPermissions[i], grantedMode, r);
3476 }
3477 }
3478
3479 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3480 intent, r);
3481
3482 if (sourceRecord == null) {
3483 // This activity is not being started from another... in this
3484 // case we -always- start a new task.
3485 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003486 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 -08003487 + intent);
3488 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3489 }
3490 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3491 // The original activity who is starting us is running as a single
3492 // instance... this new activity it is starting must go on its
3493 // own task.
3494 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3495 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3496 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3497 // The activity being started is a single instance... it always
3498 // gets launched into its own task.
3499 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3500 }
3501
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003502 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003503 // For whatever reason this activity is being launched into a new
3504 // task... yet the caller has requested a result back. Well, that
3505 // is pretty messed up, so instead immediately send back a cancel
3506 // and let the new task continue launched as normal without a
3507 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003508 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003509 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003510 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003511 Activity.RESULT_CANCELED, null);
3512 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 }
3514
3515 boolean addingToTask = false;
3516 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3517 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3518 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3519 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3520 // If bring to front is requested, and no result is requested, and
3521 // we can find a task that was started with this same
3522 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003523 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524 // See if there is a task to bring to the front. If this is
3525 // a SINGLE_INSTANCE activity, there can be one and only one
3526 // instance of it in the history, and it is always in its own
3527 // unique task, so we do a special search.
3528 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3529 ? findTaskLocked(intent, r.info)
3530 : findActivityLocked(intent, r.info);
3531 if (taskTop != null) {
3532 if (taskTop.task.intent == null) {
3533 // This task was started because of movement of
3534 // the activity based on affinity... now that we
3535 // are actually launching it, we can assign the
3536 // base intent.
3537 taskTop.task.setIntent(intent, r.info);
3538 }
3539 // If the target task is not in the front, then we need
3540 // to bring it to the front... except... well, with
3541 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3542 // to have the same behavior as if a new instance was
3543 // being started, which means not bringing it to the front
3544 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003545 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003546 if (curTop.task != taskTop.task) {
3547 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3548 boolean callerAtFront = sourceRecord == null
3549 || curTop.task == sourceRecord.task;
3550 if (callerAtFront) {
3551 // We really do want to push this one into the
3552 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003553 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003554 }
3555 }
3556 // If the caller has requested that the target task be
3557 // reset, then do so.
3558 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3559 taskTop = resetTaskIfNeededLocked(taskTop, r);
3560 }
3561 if (onlyIfNeeded) {
3562 // We don't need to start a new activity, and
3563 // the client said not to do anything if that
3564 // is the case, so this is it! And for paranoia, make
3565 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003566 if (doResume) {
3567 resumeTopActivityLocked(null);
3568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003569 return START_RETURN_INTENT_TO_CALLER;
3570 }
3571 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3572 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3573 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3574 // In this situation we want to remove all activities
3575 // from the task up to the one being started. In most
3576 // cases this means we are resetting the task to its
3577 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003578 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003579 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 if (top != null) {
3581 if (top.frontOfTask) {
3582 // Activity aliases may mean we use different
3583 // intents for the top activity, so make sure
3584 // the task now has the identity of the new
3585 // intent.
3586 top.task.setIntent(r.intent, r.info);
3587 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003588 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 deliverNewIntentLocked(top, r.intent);
3590 } else {
3591 // A special case: we need to
3592 // start the activity because it is not currently
3593 // running, and the caller has asked to clear the
3594 // current task to have this activity at the top.
3595 addingToTask = true;
3596 // Now pretend like this activity is being started
3597 // by the top of its task, so it is put in the
3598 // right place.
3599 sourceRecord = taskTop;
3600 }
3601 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3602 // In this case the top activity on the task is the
3603 // same as the one being launched, so we take that
3604 // as a request to bring the task to the foreground.
3605 // If the top activity in the task is the root
3606 // activity, deliver this new intent to it if it
3607 // desires.
3608 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3609 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003610 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 if (taskTop.frontOfTask) {
3612 taskTop.task.setIntent(r.intent, r.info);
3613 }
3614 deliverNewIntentLocked(taskTop, r.intent);
3615 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3616 // In this case we are launching the root activity
3617 // of the task, but with a different intent. We
3618 // should start a new instance on top.
3619 addingToTask = true;
3620 sourceRecord = taskTop;
3621 }
3622 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3623 // In this case an activity is being launched in to an
3624 // existing task, without resetting that task. This
3625 // is typically the situation of launching an activity
3626 // from a notification or shortcut. We want to place
3627 // the new activity on top of the current task.
3628 addingToTask = true;
3629 sourceRecord = taskTop;
3630 } else if (!taskTop.task.rootWasReset) {
3631 // In this case we are launching in to an existing task
3632 // that has not yet been started from its front door.
3633 // The current task has been brought to the front.
3634 // Ideally, we'd probably like to place this new task
3635 // at the bottom of its stack, but that's a little hard
3636 // to do with the current organization of the code so
3637 // for now we'll just drop it.
3638 taskTop.task.setIntent(r.intent, r.info);
3639 }
3640 if (!addingToTask) {
3641 // We didn't do anything... but it was needed (a.k.a., client
3642 // don't use that intent!) And for paranoia, make
3643 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003644 if (doResume) {
3645 resumeTopActivityLocked(null);
3646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 return START_TASK_TO_FRONT;
3648 }
3649 }
3650 }
3651 }
3652
3653 //String uri = r.intent.toURI();
3654 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003655 //Slog.i(TAG, "Given intent: " + r.intent);
3656 //Slog.i(TAG, "URI is: " + uri);
3657 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003658
3659 if (r.packageName != null) {
3660 // If the activity being launched is the same as the one currently
3661 // at the top, then we need to check if it should only be launched
3662 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003663 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3664 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003665 if (top.realActivity.equals(r.realActivity)) {
3666 if (top.app != null && top.app.thread != null) {
3667 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3668 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3669 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003670 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671 // For paranoia, make sure we have correctly
3672 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003673 if (doResume) {
3674 resumeTopActivityLocked(null);
3675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 if (onlyIfNeeded) {
3677 // We don't need to start a new activity, and
3678 // the client said not to do anything if that
3679 // is the case, so this is it!
3680 return START_RETURN_INTENT_TO_CALLER;
3681 }
3682 deliverNewIntentLocked(top, r.intent);
3683 return START_DELIVERED_TO_TOP;
3684 }
3685 }
3686 }
3687 }
3688
3689 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003690 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003692 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 Activity.RESULT_CANCELED, null);
3694 }
3695 return START_CLASS_NOT_FOUND;
3696 }
3697
3698 boolean newTask = false;
3699
3700 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003701 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003702 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3703 // todo: should do better management of integers.
3704 mCurTask++;
3705 if (mCurTask <= 0) {
3706 mCurTask = 1;
3707 }
3708 r.task = new TaskRecord(mCurTask, r.info, intent,
3709 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003710 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003711 + " in new task " + r.task);
3712 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003713 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714
3715 } else if (sourceRecord != null) {
3716 if (!addingToTask &&
3717 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3718 // In this case, we are adding the activity to an existing
3719 // task, but the caller has asked to clear that task if the
3720 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003721 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003722 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003723 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003724 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003725 deliverNewIntentLocked(top, r.intent);
3726 // For paranoia, make sure we have correctly
3727 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003728 if (doResume) {
3729 resumeTopActivityLocked(null);
3730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003731 return START_DELIVERED_TO_TOP;
3732 }
3733 } else if (!addingToTask &&
3734 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3735 // In this case, we are launching an activity in our own task
3736 // that may already be running somewhere in the history, and
3737 // we want to shuffle it to the front of the stack if so.
3738 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3739 if (where >= 0) {
3740 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003741 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003743 if (doResume) {
3744 resumeTopActivityLocked(null);
3745 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003746 return START_DELIVERED_TO_TOP;
3747 }
3748 }
3749 // An existing activity is starting this new activity, so we want
3750 // to keep the new one in the same task as the one that is starting
3751 // it.
3752 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003753 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 + " in existing task " + r.task);
3755
3756 } else {
3757 // This not being started from an existing activity, and not part
3758 // of a new task... just put it in the top task, though these days
3759 // this case should never happen.
3760 final int N = mHistory.size();
3761 HistoryRecord prev =
3762 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3763 r.task = prev != null
3764 ? prev.task
3765 : new TaskRecord(mCurTask, r.info, intent,
3766 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003767 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003768 + " in new guessed " + r.task);
3769 }
3770 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003771 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003772 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003773 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003774 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 return START_SUCCESS;
3776 }
3777
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003778 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3779 long thisTime, long totalTime) {
3780 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3781 WaitResult w = mWaitingActivityLaunched.get(i);
3782 w.timeout = timeout;
3783 if (r != null) {
3784 w.who = new ComponentName(r.info.packageName, r.info.name);
3785 }
3786 w.thisTime = thisTime;
3787 w.totalTime = totalTime;
3788 }
3789 notify();
3790 }
3791
3792 void reportActivityVisibleLocked(HistoryRecord r) {
3793 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3794 WaitResult w = mWaitingActivityVisible.get(i);
3795 w.timeout = false;
3796 if (r != null) {
3797 w.who = new ComponentName(r.info.packageName, r.info.name);
3798 }
3799 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3800 w.thisTime = w.totalTime;
3801 }
3802 notify();
3803 }
3804
3805 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003806 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3807 int grantedMode, IBinder resultTo,
3808 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003809 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 // Refuse possible leaked file descriptors
3811 if (intent != null && intent.hasFileDescriptors()) {
3812 throw new IllegalArgumentException("File descriptors passed in Intent");
3813 }
3814
Dianne Hackborn860755f2010-06-03 18:47:52 -07003815 boolean componentSpecified = intent.getComponent() != null;
The Android Open Source Project4df24232009-03-05 14:34:35 -08003816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003817 // Don't modify the client's object!
3818 intent = new Intent(intent);
3819
3820 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 ActivityInfo aInfo;
3822 try {
3823 ResolveInfo rInfo =
3824 ActivityThread.getPackageManager().resolveIntent(
3825 intent, resolvedType,
3826 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003827 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003828 aInfo = rInfo != null ? rInfo.activityInfo : null;
3829 } catch (RemoteException e) {
3830 aInfo = null;
3831 }
3832
3833 if (aInfo != null) {
3834 // Store the found target back into the intent, because now that
3835 // we have it we never want to do this again. For example, if the
3836 // user navigates back to this point in the history, we should
3837 // always restart the exact same activity.
3838 intent.setComponent(new ComponentName(
3839 aInfo.applicationInfo.packageName, aInfo.name));
3840
3841 // Don't debug things in the system process
3842 if (debug) {
3843 if (!aInfo.processName.equals("system")) {
3844 setDebugApp(aInfo.processName, true, false);
3845 }
3846 }
3847 }
3848
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003849 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003850 int callingPid;
3851 int callingUid;
3852 if (caller == null) {
3853 callingPid = Binder.getCallingPid();
3854 callingUid = Binder.getCallingUid();
3855 } else {
3856 callingPid = callingUid = -1;
3857 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003858
3859 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003860 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3861 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003864
Dianne Hackborn860755f2010-06-03 18:47:52 -07003865 if (aInfo != null &&
3866 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
3867 // This may be a heavy-weight process! Check to see if we already
3868 // have another, different heavy-weight process running.
3869 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
3870 if (mHeavyWeightProcess != null &&
3871 (mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
3872 !mHeavyWeightProcess.processName.equals(aInfo.processName))) {
3873 int realCallingPid = callingPid;
3874 int realCallingUid = callingUid;
3875 if (caller != null) {
3876 ProcessRecord callerApp = getRecordForAppLocked(caller);
3877 if (callerApp != null) {
3878 realCallingPid = callerApp.pid;
3879 realCallingUid = callerApp.info.uid;
3880 } else {
3881 Slog.w(TAG, "Unable to find app for caller " + caller
3882 + " (pid=" + realCallingPid + ") when starting: "
3883 + intent.toString());
3884 return START_PERMISSION_DENIED;
3885 }
3886 }
3887
3888 IIntentSender target = getIntentSenderLocked(
3889 IActivityManager.INTENT_SENDER_ACTIVITY, "android",
3890 realCallingUid, null, null, 0, intent,
3891 resolvedType, PendingIntent.FLAG_CANCEL_CURRENT
3892 | PendingIntent.FLAG_ONE_SHOT);
3893
3894 Intent newIntent = new Intent();
3895 if (requestCode >= 0) {
3896 // Caller is requesting a result.
3897 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3898 }
3899 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
3900 new IntentSender(target));
3901 if (mHeavyWeightProcess.activities.size() > 0) {
3902 HistoryRecord hist = mHeavyWeightProcess.activities.get(0);
3903 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
3904 hist.packageName);
3905 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3906 hist.task.taskId);
3907 }
3908 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3909 aInfo.packageName);
3910 newIntent.setFlags(intent.getFlags());
3911 newIntent.setClassName("android",
3912 HeavyWeightSwitcherActivity.class.getName());
3913 intent = newIntent;
3914 resolvedType = null;
3915 caller = null;
3916 callingUid = Binder.getCallingUid();
3917 callingPid = Binder.getCallingPid();
3918 componentSpecified = true;
3919 try {
3920 ResolveInfo rInfo =
3921 ActivityThread.getPackageManager().resolveIntent(
3922 intent, null,
3923 PackageManager.MATCH_DEFAULT_ONLY
3924 | STOCK_PM_FLAGS);
3925 aInfo = rInfo != null ? rInfo.activityInfo : null;
3926 } catch (RemoteException e) {
3927 aInfo = null;
3928 }
3929 }
3930 }
3931 }
3932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003933 int res = startActivityLocked(caller, intent, resolvedType,
3934 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003935 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003936 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003937
Dianne Hackborne2522462010-03-29 18:41:30 -07003938 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003939 // If the caller also wants to switch to a new configuration,
3940 // do so now. This allows a clean switch, as we are waiting
3941 // for the current activity to pause (so we will not destroy
3942 // it), and have not yet started the next activity.
3943 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3944 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003945 mConfigWillChange = false;
3946 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3947 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003948 updateConfigurationLocked(config, null);
3949 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003952
3953 if (outResult != null) {
3954 outResult.result = res;
3955 if (res == IActivityManager.START_SUCCESS) {
3956 mWaitingActivityLaunched.add(outResult);
3957 do {
3958 try {
3959 wait();
3960 } catch (InterruptedException e) {
3961 }
3962 } while (!outResult.timeout && outResult.who == null);
3963 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3964 HistoryRecord r = this.topRunningActivityLocked(null);
3965 if (r.nowVisible) {
3966 outResult.timeout = false;
3967 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3968 outResult.totalTime = 0;
3969 outResult.thisTime = 0;
3970 } else {
3971 outResult.thisTime = SystemClock.uptimeMillis();
3972 mWaitingActivityVisible.add(outResult);
3973 do {
3974 try {
3975 wait();
3976 } catch (InterruptedException e) {
3977 }
3978 } while (!outResult.timeout && outResult.who == null);
3979 }
3980 }
3981 }
3982
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 return res;
3984 }
3985 }
3986
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003987 public final int startActivity(IApplicationThread caller,
3988 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3989 int grantedMode, IBinder resultTo,
3990 String resultWho, int requestCode, boolean onlyIfNeeded,
3991 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003992 return startActivityMayWait(caller, intent, resolvedType,
3993 grantedUriPermissions, grantedMode, resultTo, resultWho,
3994 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003995 }
3996
3997 public final WaitResult startActivityAndWait(IApplicationThread caller,
3998 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3999 int grantedMode, IBinder resultTo,
4000 String resultWho, int requestCode, boolean onlyIfNeeded,
4001 boolean debug) {
4002 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07004003 startActivityMayWait(caller, intent, resolvedType,
4004 grantedUriPermissions, grantedMode, resultTo, resultWho,
4005 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08004006 return res;
4007 }
4008
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07004009 public final int startActivityWithConfig(IApplicationThread caller,
4010 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
4011 int grantedMode, IBinder resultTo,
4012 String resultWho, int requestCode, boolean onlyIfNeeded,
4013 boolean debug, Configuration config) {
4014 return startActivityMayWait(caller, intent, resolvedType,
4015 grantedUriPermissions, grantedMode, resultTo, resultWho,
4016 requestCode, onlyIfNeeded, debug, null, config);
4017 }
4018
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08004019 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07004020 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07004021 IBinder resultTo, String resultWho, int requestCode,
4022 int flagsMask, int flagsValues) {
4023 // Refuse possible leaked file descriptors
4024 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
4025 throw new IllegalArgumentException("File descriptors passed in Intent");
4026 }
4027
4028 IIntentSender sender = intent.getTarget();
4029 if (!(sender instanceof PendingIntentRecord)) {
4030 throw new IllegalArgumentException("Bad PendingIntent object");
4031 }
4032
4033 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07004034
4035 synchronized (this) {
4036 // If this is coming from the currently resumed activity, it is
4037 // effectively saying that app switches are allowed at this point.
4038 if (mResumedActivity != null
4039 && mResumedActivity.info.applicationInfo.uid ==
4040 Binder.getCallingUid()) {
4041 mAppSwitchesAllowedTime = 0;
4042 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07004043 }
4044
4045 return pir.sendInner(0, fillInIntent, resolvedType,
4046 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
4047 }
4048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004049 public boolean startNextMatchingActivity(IBinder callingActivity,
4050 Intent intent) {
4051 // Refuse possible leaked file descriptors
4052 if (intent != null && intent.hasFileDescriptors() == true) {
4053 throw new IllegalArgumentException("File descriptors passed in Intent");
4054 }
4055
4056 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004057 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004058 if (index < 0) {
4059 return false;
4060 }
4061 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4062 if (r.app == null || r.app.thread == null) {
4063 // The caller is not running... d'oh!
4064 return false;
4065 }
4066 intent = new Intent(intent);
4067 // The caller is not allowed to change the data.
4068 intent.setDataAndType(r.intent.getData(), r.intent.getType());
4069 // And we are resetting to find the next component...
4070 intent.setComponent(null);
4071
4072 ActivityInfo aInfo = null;
4073 try {
4074 List<ResolveInfo> resolves =
4075 ActivityThread.getPackageManager().queryIntentActivities(
4076 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004077 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004078
4079 // Look for the original activity in the list...
4080 final int N = resolves != null ? resolves.size() : 0;
4081 for (int i=0; i<N; i++) {
4082 ResolveInfo rInfo = resolves.get(i);
4083 if (rInfo.activityInfo.packageName.equals(r.packageName)
4084 && rInfo.activityInfo.name.equals(r.info.name)) {
4085 // We found the current one... the next matching is
4086 // after it.
4087 i++;
4088 if (i<N) {
4089 aInfo = resolves.get(i).activityInfo;
4090 }
4091 break;
4092 }
4093 }
4094 } catch (RemoteException e) {
4095 }
4096
4097 if (aInfo == null) {
4098 // Nobody who is next!
4099 return false;
4100 }
4101
4102 intent.setComponent(new ComponentName(
4103 aInfo.applicationInfo.packageName, aInfo.name));
4104 intent.setFlags(intent.getFlags()&~(
4105 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
4106 Intent.FLAG_ACTIVITY_CLEAR_TOP|
4107 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
4108 Intent.FLAG_ACTIVITY_NEW_TASK));
4109
4110 // Okay now we need to start the new activity, replacing the
4111 // currently running activity. This is a little tricky because
4112 // we want to start the new one as if the current one is finished,
4113 // but not finish the current one first so that there is no flicker.
4114 // And thus...
4115 final boolean wasFinishing = r.finishing;
4116 r.finishing = true;
4117
4118 // Propagate reply information over to the new activity.
4119 final HistoryRecord resultTo = r.resultTo;
4120 final String resultWho = r.resultWho;
4121 final int requestCode = r.requestCode;
4122 r.resultTo = null;
4123 if (resultTo != null) {
4124 resultTo.removeResultsLocked(r, resultWho, requestCode);
4125 }
4126
4127 final long origId = Binder.clearCallingIdentity();
4128 // XXX we are not dealing with propagating grantedUriPermissions...
4129 // those are not yet exposed to user code, so there is no need.
4130 int res = startActivityLocked(r.app.thread, intent,
4131 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004132 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004133 Binder.restoreCallingIdentity(origId);
4134
4135 r.finishing = wasFinishing;
4136 if (res != START_SUCCESS) {
4137 return false;
4138 }
4139 return true;
4140 }
4141 }
4142
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004143 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004144 Intent intent, String resolvedType, IBinder resultTo,
4145 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004146
4147 // This is so super not safe, that only the system (or okay root)
4148 // can do it.
4149 final int callingUid = Binder.getCallingUid();
4150 if (callingUid != 0 && callingUid != Process.myUid()) {
4151 throw new SecurityException(
4152 "startActivityInPackage only available to the system");
4153 }
4154
The Android Open Source Project4df24232009-03-05 14:34:35 -08004155 final boolean componentSpecified = intent.getComponent() != null;
4156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 // Don't modify the client's object!
4158 intent = new Intent(intent);
4159
4160 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 ActivityInfo aInfo;
4162 try {
4163 ResolveInfo rInfo =
4164 ActivityThread.getPackageManager().resolveIntent(
4165 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004166 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004167 aInfo = rInfo != null ? rInfo.activityInfo : null;
4168 } catch (RemoteException e) {
4169 aInfo = null;
4170 }
4171
4172 if (aInfo != null) {
4173 // Store the found target back into the intent, because now that
4174 // we have it we never want to do this again. For example, if the
4175 // user navigates back to this point in the history, we should
4176 // always restart the exact same activity.
4177 intent.setComponent(new ComponentName(
4178 aInfo.applicationInfo.packageName, aInfo.name));
4179 }
4180
4181 synchronized(this) {
4182 return startActivityLocked(null, intent, resolvedType,
4183 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004184 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004185 }
4186 }
4187
Josh Bartel7f208742010-02-25 11:01:44 -06004188 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 // Remove any existing entries that are the same kind of task.
4190 int N = mRecentTasks.size();
4191 for (int i=0; i<N; i++) {
4192 TaskRecord tr = mRecentTasks.get(i);
4193 if ((task.affinity != null && task.affinity.equals(tr.affinity))
4194 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
4195 mRecentTasks.remove(i);
4196 i--;
4197 N--;
4198 if (task.intent == null) {
4199 // If the new recent task we are adding is not fully
4200 // specified, then replace it with the existing recent task.
4201 task = tr;
4202 }
4203 }
4204 }
4205 if (N >= MAX_RECENT_TASKS) {
4206 mRecentTasks.remove(N-1);
4207 }
4208 mRecentTasks.add(0, task);
4209 }
4210
4211 public void setRequestedOrientation(IBinder token,
4212 int requestedOrientation) {
4213 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004214 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004215 if (index < 0) {
4216 return;
4217 }
4218 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4219 final long origId = Binder.clearCallingIdentity();
4220 mWindowManager.setAppOrientation(r, requestedOrientation);
4221 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07004222 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 r.mayFreezeScreenLocked(r.app) ? r : null);
4224 if (config != null) {
4225 r.frozenBeforeDestroy = true;
4226 if (!updateConfigurationLocked(config, r)) {
4227 resumeTopActivityLocked(null);
4228 }
4229 }
4230 Binder.restoreCallingIdentity(origId);
4231 }
4232 }
4233
4234 public int getRequestedOrientation(IBinder token) {
4235 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004236 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 if (index < 0) {
4238 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
4239 }
4240 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4241 return mWindowManager.getAppOrientation(r);
4242 }
4243 }
4244
4245 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004246 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004247 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4248 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
4249 if (!r.finishing) {
4250 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
4251 "no-history");
4252 }
4253 } else if (r.app != null && r.app.thread != null) {
4254 if (mFocusedActivity == r) {
4255 setFocusedActivityLocked(topRunningActivityLocked(null));
4256 }
4257 r.resumeKeyDispatchingLocked();
4258 try {
4259 r.stopped = false;
4260 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004261 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004262 TAG, "Stopping visible=" + r.visible + " for " + r);
4263 if (!r.visible) {
4264 mWindowManager.setAppVisibility(r, false);
4265 }
4266 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4267 } catch (Exception e) {
4268 // Maybe just ignore exceptions here... if the process
4269 // has crashed, our death notification will clean things
4270 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004271 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 // Just in case, assume it to be stopped.
4273 r.stopped = true;
4274 r.state = ActivityState.STOPPED;
4275 if (r.configDestroy) {
4276 destroyActivityLocked(r, true);
4277 }
4278 }
4279 }
4280 }
4281
4282 /**
4283 * @return Returns true if the activity is being finished, false if for
4284 * some reason it is being left as-is.
4285 */
4286 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4287 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004288 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 TAG, "Finishing activity: token=" + token
4290 + ", result=" + resultCode + ", data=" + resultData);
4291
Dianne Hackborn75b03852009-06-12 15:43:26 -07004292 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004293 if (index < 0) {
4294 return false;
4295 }
4296 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4297
4298 // Is this the last activity left?
4299 boolean lastActivity = true;
4300 for (int i=mHistory.size()-1; i>=0; i--) {
4301 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4302 if (!p.finishing && p != r) {
4303 lastActivity = false;
4304 break;
4305 }
4306 }
4307
4308 // If this is the last activity, but it is the home activity, then
4309 // just don't finish it.
4310 if (lastActivity) {
4311 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4312 return false;
4313 }
4314 }
4315
4316 finishActivityLocked(r, index, resultCode, resultData, reason);
4317 return true;
4318 }
4319
4320 /**
4321 * @return Returns true if this activity has been removed from the history
4322 * list, or false if it is still in the list and will be removed later.
4323 */
4324 private final boolean finishActivityLocked(HistoryRecord r, int index,
4325 int resultCode, Intent resultData, String reason) {
4326 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004327 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004328 return false;
4329 }
4330
4331 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004332 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004333 System.identityHashCode(r),
4334 r.task.taskId, r.shortComponentName, reason);
4335 r.task.numActivities--;
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004336 if (index < (mHistory.size()-1)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004337 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4338 if (next.task == r.task) {
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004339 if (r.frontOfTask) {
4340 // The next activity is now the front of the task.
4341 next.frontOfTask = true;
4342 }
4343 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4344 // If the caller asked that this activity (and all above it)
4345 // be cleared when the task is reset, don't lose that information,
4346 // but propagate it up to the next activity.
4347 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 }
4350 }
4351
4352 r.pauseKeyDispatchingLocked();
4353 if (mFocusedActivity == r) {
4354 setFocusedActivityLocked(topRunningActivityLocked(null));
4355 }
4356
4357 // send the result
4358 HistoryRecord resultTo = r.resultTo;
4359 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004360 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004361 + " who=" + r.resultWho + " req=" + r.requestCode
4362 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 if (r.info.applicationInfo.uid > 0) {
4364 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4365 r.packageName, resultData, r);
4366 }
4367 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4368 resultData);
4369 r.resultTo = null;
4370 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004371 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372
4373 // Make sure this HistoryRecord is not holding on to other resources,
4374 // because clients have remote IPC references to this object so we
4375 // can't assume that will go away and want to avoid circular IPC refs.
4376 r.results = null;
4377 r.pendingResults = null;
4378 r.newIntents = null;
4379 r.icicle = null;
4380
4381 if (mPendingThumbnails.size() > 0) {
4382 // There are clients waiting to receive thumbnails so, in case
4383 // this is an activity that someone is waiting for, add it
4384 // to the pending list so we can correctly update the clients.
4385 mCancelledThumbnails.add(r);
4386 }
4387
4388 if (mResumedActivity == r) {
4389 boolean endTask = index <= 0
4390 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004391 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004392 "Prepare close transition: finishing " + r);
4393 mWindowManager.prepareAppTransition(endTask
4394 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4395 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4396
4397 // Tell window manager to prepare for this one to be removed.
4398 mWindowManager.setAppVisibility(r, false);
4399
4400 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004401 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4402 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 startPausingLocked(false, false);
4404 }
4405
4406 } else if (r.state != ActivityState.PAUSING) {
4407 // If the activity is PAUSING, we will complete the finish once
4408 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004409 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 return finishCurrentActivityLocked(r, index,
4411 FINISH_AFTER_PAUSE) == null;
4412 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004413 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004414 }
4415
4416 return false;
4417 }
4418
4419 private static final int FINISH_IMMEDIATELY = 0;
4420 private static final int FINISH_AFTER_PAUSE = 1;
4421 private static final int FINISH_AFTER_VISIBLE = 2;
4422
4423 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4424 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004425 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004426 if (index < 0) {
4427 return null;
4428 }
4429
4430 return finishCurrentActivityLocked(r, index, mode);
4431 }
4432
4433 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4434 int index, int mode) {
4435 // First things first: if this activity is currently visible,
4436 // and the resumed activity is not yet visible, then hold off on
4437 // finishing until the resumed one becomes visible.
4438 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4439 if (!mStoppingActivities.contains(r)) {
4440 mStoppingActivities.add(r);
4441 if (mStoppingActivities.size() > 3) {
4442 // If we already have a few activities waiting to stop,
4443 // then give up on things going idle and start clearing
4444 // them out.
4445 Message msg = Message.obtain();
4446 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4447 mHandler.sendMessage(msg);
4448 }
4449 }
4450 r.state = ActivityState.STOPPING;
4451 updateOomAdjLocked();
4452 return r;
4453 }
4454
4455 // make sure the record is cleaned out of other places.
4456 mStoppingActivities.remove(r);
4457 mWaitingVisibleActivities.remove(r);
4458 if (mResumedActivity == r) {
4459 mResumedActivity = null;
4460 }
4461 final ActivityState prevState = r.state;
4462 r.state = ActivityState.FINISHING;
4463
4464 if (mode == FINISH_IMMEDIATELY
4465 || prevState == ActivityState.STOPPED
4466 || prevState == ActivityState.INITIALIZING) {
4467 // If this activity is already stopped, we can just finish
4468 // it right now.
4469 return destroyActivityLocked(r, true) ? null : r;
4470 } else {
4471 // Need to go through the full pause cycle to get this
4472 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004473 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004474 mFinishingActivities.add(r);
4475 resumeTopActivityLocked(null);
4476 }
4477 return r;
4478 }
4479
4480 /**
4481 * This is the internal entry point for handling Activity.finish().
4482 *
4483 * @param token The Binder token referencing the Activity we want to finish.
4484 * @param resultCode Result code, if any, from this Activity.
4485 * @param resultData Result data (Intent), if any, from this Activity.
4486 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004487 * @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 -08004488 */
4489 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4490 // Refuse possible leaked file descriptors
4491 if (resultData != null && resultData.hasFileDescriptors() == true) {
4492 throw new IllegalArgumentException("File descriptors passed in Intent");
4493 }
4494
4495 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004496 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 // Find the first activity that is not finishing.
4498 HistoryRecord next = topRunningActivityLocked(token, 0);
4499 if (next != null) {
4500 // ask watcher if this is allowed
4501 boolean resumeOK = true;
4502 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004503 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004505 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 }
4507
4508 if (!resumeOK) {
4509 return false;
4510 }
4511 }
4512 }
4513 final long origId = Binder.clearCallingIdentity();
4514 boolean res = requestFinishActivityLocked(token, resultCode,
4515 resultData, "app-request");
4516 Binder.restoreCallingIdentity(origId);
4517 return res;
4518 }
4519 }
4520
Dianne Hackborn860755f2010-06-03 18:47:52 -07004521 public final void finishHeavyWeightApp() {
4522 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4523 != PackageManager.PERMISSION_GRANTED) {
4524 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
4525 + Binder.getCallingPid()
4526 + ", uid=" + Binder.getCallingUid()
4527 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4528 Slog.w(TAG, msg);
4529 throw new SecurityException(msg);
4530 }
4531
4532 synchronized(this) {
4533 if (mHeavyWeightProcess == null) {
4534 return;
4535 }
4536
4537 ArrayList<HistoryRecord> activities = new ArrayList<HistoryRecord>(
4538 mHeavyWeightProcess.activities);
4539 for (int i=0; i<activities.size(); i++) {
4540 HistoryRecord r = activities.get(i);
4541 if (!r.finishing) {
4542 int index = indexOfTokenLocked(r);
4543 if (index >= 0) {
4544 finishActivityLocked(r, index, Activity.RESULT_CANCELED,
4545 null, "finish-heavy");
4546 }
4547 }
4548 }
4549
4550 mHeavyWeightProcess = null;
4551 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4552 }
4553 }
4554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004555 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4556 String resultWho, int requestCode, int resultCode, Intent data) {
4557
4558 if (callingUid > 0) {
4559 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4560 data, r);
4561 }
4562
Joe Onorato8a9b2202010-02-26 18:56:32 -08004563 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004564 + " : who=" + resultWho + " req=" + requestCode
4565 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004566 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4567 try {
4568 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4569 list.add(new ResultInfo(resultWho, requestCode,
4570 resultCode, data));
4571 r.app.thread.scheduleSendResult(r, list);
4572 return;
4573 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004574 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 }
4576 }
4577
4578 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4579 }
4580
4581 public final void finishSubActivity(IBinder token, String resultWho,
4582 int requestCode) {
4583 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004584 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 if (index < 0) {
4586 return;
4587 }
4588 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4589
4590 final long origId = Binder.clearCallingIdentity();
4591
4592 int i;
4593 for (i=mHistory.size()-1; i>=0; i--) {
4594 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4595 if (r.resultTo == self && r.requestCode == requestCode) {
4596 if ((r.resultWho == null && resultWho == null) ||
4597 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4598 finishActivityLocked(r, i,
4599 Activity.RESULT_CANCELED, null, "request-sub");
4600 }
4601 }
4602 }
4603
4604 Binder.restoreCallingIdentity(origId);
4605 }
4606 }
4607
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004608 public boolean willActivityBeVisible(IBinder token) {
4609 synchronized(this) {
4610 int i;
4611 for (i=mHistory.size()-1; i>=0; i--) {
4612 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4613 if (r == token) {
4614 return true;
4615 }
4616 if (r.fullscreen && !r.finishing) {
4617 return false;
4618 }
4619 }
4620 return true;
4621 }
4622 }
4623
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004624 public void overridePendingTransition(IBinder token, String packageName,
4625 int enterAnim, int exitAnim) {
4626 synchronized(this) {
4627 int index = indexOfTokenLocked(token);
4628 if (index < 0) {
4629 return;
4630 }
4631 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4632
4633 final long origId = Binder.clearCallingIdentity();
4634
4635 if (self.state == ActivityState.RESUMED
4636 || self.state == ActivityState.PAUSING) {
4637 mWindowManager.overridePendingAppTransition(packageName,
4638 enterAnim, exitAnim);
4639 }
4640
4641 Binder.restoreCallingIdentity(origId);
4642 }
4643 }
4644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 /**
4646 * Perform clean-up of service connections in an activity record.
4647 */
4648 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4649 // Throw away any services that have been bound by this activity.
4650 if (r.connections != null) {
4651 Iterator<ConnectionRecord> it = r.connections.iterator();
4652 while (it.hasNext()) {
4653 ConnectionRecord c = it.next();
4654 removeConnectionLocked(c, null, r);
4655 }
4656 r.connections = null;
4657 }
4658 }
4659
4660 /**
4661 * Perform the common clean-up of an activity record. This is called both
4662 * as part of destroyActivityLocked() (when destroying the client-side
4663 * representation) and cleaning things up as a result of its hosting
4664 * processing going away, in which case there is no remaining client-side
4665 * state to destroy so only the cleanup here is needed.
4666 */
4667 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4668 if (mResumedActivity == r) {
4669 mResumedActivity = null;
4670 }
4671 if (mFocusedActivity == r) {
4672 mFocusedActivity = null;
4673 }
4674
4675 r.configDestroy = false;
4676 r.frozenBeforeDestroy = false;
4677
4678 // Make sure this record is no longer in the pending finishes list.
4679 // This could happen, for example, if we are trimming activities
4680 // down to the max limit while they are still waiting to finish.
4681 mFinishingActivities.remove(r);
4682 mWaitingVisibleActivities.remove(r);
4683
4684 // Remove any pending results.
4685 if (r.finishing && r.pendingResults != null) {
4686 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4687 PendingIntentRecord rec = apr.get();
4688 if (rec != null) {
4689 cancelIntentSenderLocked(rec, false);
4690 }
4691 }
4692 r.pendingResults = null;
4693 }
4694
4695 if (cleanServices) {
4696 cleanUpActivityServicesLocked(r);
4697 }
4698
4699 if (mPendingThumbnails.size() > 0) {
4700 // There are clients waiting to receive thumbnails so, in case
4701 // this is an activity that someone is waiting for, add it
4702 // to the pending list so we can correctly update the clients.
4703 mCancelledThumbnails.add(r);
4704 }
4705
4706 // Get rid of any pending idle timeouts.
4707 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4708 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4709 }
4710
4711 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4712 if (r.state != ActivityState.DESTROYED) {
4713 mHistory.remove(r);
4714 r.inHistory = false;
4715 r.state = ActivityState.DESTROYED;
4716 mWindowManager.removeAppToken(r);
4717 if (VALIDATE_TOKENS) {
4718 mWindowManager.validateAppTokens(mHistory);
4719 }
4720 cleanUpActivityServicesLocked(r);
4721 removeActivityUriPermissionsLocked(r);
4722 }
4723 }
4724
4725 /**
4726 * Destroy the current CLIENT SIDE instance of an activity. This may be
4727 * called both when actually finishing an activity, or when performing
4728 * a configuration switch where we destroy the current client-side object
4729 * but then create a new client-side object for this same HistoryRecord.
4730 */
4731 private final boolean destroyActivityLocked(HistoryRecord r,
4732 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004733 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 TAG, "Removing activity: token=" + r
4735 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004736 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004737 System.identityHashCode(r),
4738 r.task.taskId, r.shortComponentName);
4739
4740 boolean removedFromHistory = false;
4741
4742 cleanUpActivityLocked(r, false);
4743
Dianne Hackborn03abb812010-01-04 18:43:19 -08004744 final boolean hadApp = r.app != null;
4745
4746 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 if (removeFromApp) {
4748 int idx = r.app.activities.indexOf(r);
4749 if (idx >= 0) {
4750 r.app.activities.remove(idx);
4751 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004752 if (mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4753 mHeavyWeightProcess = null;
4754 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4755 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 if (r.persistent) {
4757 decPersistentCountLocked(r.app);
4758 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004759 if (r.app.activities.size() == 0) {
4760 // No longer have activities, so update location in
4761 // LRU list.
4762 updateLruProcessLocked(r.app, true, false);
4763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004764 }
4765
4766 boolean skipDestroy = false;
4767
4768 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004769 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4771 r.configChangeFlags);
4772 } catch (Exception e) {
4773 // We can just ignore exceptions here... if the process
4774 // has crashed, our death notification will clean things
4775 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004776 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 if (r.finishing) {
4778 removeActivityFromHistoryLocked(r);
4779 removedFromHistory = true;
4780 skipDestroy = true;
4781 }
4782 }
4783
4784 r.app = null;
4785 r.nowVisible = false;
4786
4787 if (r.finishing && !skipDestroy) {
4788 r.state = ActivityState.DESTROYING;
4789 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4790 msg.obj = r;
4791 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4792 } else {
4793 r.state = ActivityState.DESTROYED;
4794 }
4795 } else {
4796 // remove this record from the history.
4797 if (r.finishing) {
4798 removeActivityFromHistoryLocked(r);
4799 removedFromHistory = true;
4800 } else {
4801 r.state = ActivityState.DESTROYED;
4802 }
4803 }
4804
4805 r.configChangeFlags = 0;
4806
Dianne Hackborn03abb812010-01-04 18:43:19 -08004807 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004808 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004809 }
4810
4811 return removedFromHistory;
4812 }
4813
Dianne Hackborn03abb812010-01-04 18:43:19 -08004814 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004816 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004817 TAG, "Removing app " + app + " from list " + list
4818 + " with " + i + " entries");
4819 while (i > 0) {
4820 i--;
4821 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004822 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004823 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4824 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004825 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 list.remove(i);
4827 }
4828 }
4829 }
4830
4831 /**
4832 * Main function for removing an existing process from the activity manager
4833 * as a result of that process going away. Clears out all connections
4834 * to the process.
4835 */
4836 private final void handleAppDiedLocked(ProcessRecord app,
4837 boolean restarting) {
4838 cleanUpApplicationRecordLocked(app, restarting, -1);
4839 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004840 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 }
4842
4843 // Just in case...
4844 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004845 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004846 mPausingActivity = null;
4847 }
4848 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4849 mLastPausedActivity = null;
4850 }
4851
4852 // Remove this application's activities from active lists.
4853 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4854 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4855 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4856 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4857
4858 boolean atTop = true;
4859 boolean hasVisibleActivities = false;
4860
4861 // Clean out the history list.
4862 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004863 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004864 TAG, "Removing app " + app + " from history with " + i + " entries");
4865 while (i > 0) {
4866 i--;
4867 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004868 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004869 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4870 if (r.app == app) {
4871 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
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 this entry! frozen=" + r.haveState
4874 + " finishing=" + r.finishing);
4875 mHistory.remove(i);
4876
4877 r.inHistory = false;
4878 mWindowManager.removeAppToken(r);
4879 if (VALIDATE_TOKENS) {
4880 mWindowManager.validateAppTokens(mHistory);
4881 }
4882 removeActivityUriPermissionsLocked(r);
4883
4884 } else {
4885 // We have the current state for this activity, so
4886 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004887 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004888 TAG, "Keeping entry, setting app to null");
4889 if (r.visible) {
4890 hasVisibleActivities = true;
4891 }
4892 r.app = null;
4893 r.nowVisible = false;
4894 if (!r.haveState) {
4895 r.icicle = null;
4896 }
4897 }
4898
4899 cleanUpActivityLocked(r, true);
4900 r.state = ActivityState.STOPPED;
4901 }
4902 atTop = false;
4903 }
4904
4905 app.activities.clear();
4906
4907 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004908 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004909 + " running instrumentation " + app.instrumentationClass);
4910 Bundle info = new Bundle();
4911 info.putString("shortMsg", "Process crashed.");
4912 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4913 }
4914
4915 if (!restarting) {
4916 if (!resumeTopActivityLocked(null)) {
4917 // If there was nothing to resume, and we are not already
4918 // restarting this process, but there is a visible activity that
4919 // is hosted by the process... then make sure all visible
4920 // activities are running, taking care of restarting this
4921 // process.
4922 if (hasVisibleActivities) {
4923 ensureActivitiesVisibleLocked(null, 0);
4924 }
4925 }
4926 }
4927 }
4928
4929 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4930 IBinder threadBinder = thread.asBinder();
4931
4932 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004933 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4934 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004935 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4936 return i;
4937 }
4938 }
4939 return -1;
4940 }
4941
4942 private final ProcessRecord getRecordForAppLocked(
4943 IApplicationThread thread) {
4944 if (thread == null) {
4945 return null;
4946 }
4947
4948 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004949 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004950 }
4951
4952 private final void appDiedLocked(ProcessRecord app, int pid,
4953 IApplicationThread thread) {
4954
4955 mProcDeaths[0]++;
4956
Magnus Edlund7bb25812010-02-24 15:45:06 +01004957 // Clean up already done if the process has been re-started.
4958 if (app.pid == pid && app.thread != null &&
4959 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07004960 if (!app.killedBackground) {
4961 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
4962 + ") has died.");
4963 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08004964 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004965 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004966 TAG, "Dying app: " + app + ", pid: " + pid
4967 + ", thread: " + thread.asBinder());
4968 boolean doLowMem = app.instrumentationClass == null;
4969 handleAppDiedLocked(app, false);
4970
4971 if (doLowMem) {
4972 // If there are no longer any background processes running,
4973 // and the app that died was not running instrumentation,
4974 // then tell everyone we are now low on memory.
4975 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004976 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4977 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004978 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4979 haveBg = true;
4980 break;
4981 }
4982 }
4983
4984 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004985 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004986 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004987 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004988 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4989 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004990 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004991 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4992 // The low memory report is overriding any current
4993 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07004994 // heavy/important/visible/foreground processes first.
4995 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004996 rec.lastRequestedGc = 0;
4997 } else {
4998 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005000 rec.reportLowMemory = true;
5001 rec.lastLowMemory = now;
5002 mProcessesToGc.remove(rec);
5003 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005004 }
5005 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005006 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005007 }
5008 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01005009 } else if (app.pid != pid) {
5010 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005011 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01005012 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08005013 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005014 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005015 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 + thread.asBinder());
5017 }
5018 }
5019
Dan Egnor42471dd2010-01-07 17:25:22 -08005020 /**
5021 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07005022 * @param clearTraces causes the dump file to be erased prior to the new
5023 * traces being written, if true; when false, the new traces will be
5024 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08005025 * @param pids of dalvik VM processes to dump stack traces for
5026 * @return file containing stack traces, or null if no dump file is configured
5027 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07005028 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005029 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
5030 if (tracesPath == null || tracesPath.length() == 0) {
5031 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005033
5034 File tracesFile = new File(tracesPath);
5035 try {
5036 File tracesDir = tracesFile.getParentFile();
5037 if (!tracesDir.exists()) tracesFile.mkdirs();
5038 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
5039
Christopher Tate6ee412d2010-05-28 12:01:56 -07005040 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08005041 tracesFile.createNewFile();
5042 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
5043 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005044 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005045 return null;
5046 }
5047
5048 // Use a FileObserver to detect when traces finish writing.
5049 // The order of traces is considered important to maintain for legibility.
5050 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
5051 public synchronized void onEvent(int event, String path) { notify(); }
5052 };
5053
5054 try {
5055 observer.startWatching();
5056 int num = pids.size();
5057 for (int i = 0; i < num; i++) {
5058 synchronized (observer) {
5059 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
5060 observer.wait(200); // Wait for write-close, give up after 200msec
5061 }
5062 }
5063 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08005064 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005065 } finally {
5066 observer.stopWatching();
5067 }
5068
5069 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005070 }
5071
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005072 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08005073 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005074 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005075
5076 synchronized (this) {
5077 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
5078 if (mShuttingDown) {
5079 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
5080 return;
5081 } else if (app.notResponding) {
5082 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
5083 return;
5084 } else if (app.crashing) {
5085 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
5086 return;
5087 }
5088
5089 // In case we come through here for the same app before completing
5090 // this one, mark as anring now so we will bail out.
5091 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08005092
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005093 // Log the ANR to the event log.
5094 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
5095 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08005096
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005097 // Dump thread traces as quickly as we can, starting with "interesting" processes.
5098 pids.add(app.pid);
5099
5100 int parentPid = app.pid;
5101 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
5102 if (parentPid != app.pid) pids.add(parentPid);
5103
5104 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08005105
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005106 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
5107 ProcessRecord r = mLruProcesses.get(i);
5108 if (r != null && r.thread != null) {
5109 int pid = r.pid;
5110 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
5111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 }
5113 }
5114
Christopher Tate6ee412d2010-05-28 12:01:56 -07005115 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08005116
5117 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005118 StringBuilder info = mStringBuilder;
5119 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08005120 info.append("ANR in ").append(app.processName);
5121 if (activity != null && activity.shortComponentName != null) {
5122 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07005123 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08005124 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005125 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005126 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005127 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005128 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005129 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005131
Dan Egnor42471dd2010-01-07 17:25:22 -08005132 String cpuInfo = null;
5133 if (MONITOR_CPU_USAGE) {
5134 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005135 synchronized (mProcessStatsThread) {
5136 cpuInfo = mProcessStats.printCurrentState();
5137 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005138 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 }
5140
Joe Onorato8a9b2202010-02-26 18:56:32 -08005141 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08005142 if (tracesFile == null) {
5143 // There is no trace file, so dump (only) the alleged culprit's threads to the log
5144 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
5145 }
5146
5147 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
5148
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005149 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005150 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08005151 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
5152 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005154 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
5155 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005156 }
5157 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005158 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005159 }
5160 }
5161
Dan Egnor42471dd2010-01-07 17:25:22 -08005162 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
5163 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
5164 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005165
5166 synchronized (this) {
5167 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
5168 Process.killProcess(app.pid);
5169 return;
5170 }
5171
5172 // Set the app's notResponding state, and look up the errorReportReceiver
5173 makeAppNotRespondingLocked(app,
5174 activity != null ? activity.shortComponentName : null,
5175 annotation != null ? "ANR " + annotation : "ANR",
5176 info.toString());
5177
5178 // Bring up the infamous App Not Responding dialog
5179 Message msg = Message.obtain();
5180 HashMap map = new HashMap();
5181 msg.what = SHOW_NOT_RESPONDING_MSG;
5182 msg.obj = map;
5183 map.put("app", app);
5184 if (activity != null) {
5185 map.put("activity", activity);
5186 }
5187
5188 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08005189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005190 }
5191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005192 private final void decPersistentCountLocked(ProcessRecord app)
5193 {
5194 app.persistentActivities--;
5195 if (app.persistentActivities > 0) {
5196 // Still more of 'em...
5197 return;
5198 }
5199 if (app.persistent) {
5200 // Ah, but the application itself is persistent. Whatever!
5201 return;
5202 }
5203
5204 // App is no longer persistent... make sure it and the ones
5205 // following it in the LRU list have the correc oom_adj.
5206 updateOomAdjLocked();
5207 }
5208
5209 public void setPersistent(IBinder token, boolean isPersistent) {
5210 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
5211 != PackageManager.PERMISSION_GRANTED) {
5212 String msg = "Permission Denial: setPersistent() from pid="
5213 + Binder.getCallingPid()
5214 + ", uid=" + Binder.getCallingUid()
5215 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005216 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005217 throw new SecurityException(msg);
5218 }
5219
5220 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005221 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005222 if (index < 0) {
5223 return;
5224 }
5225 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5226 ProcessRecord app = r.app;
5227
Joe Onorato8a9b2202010-02-26 18:56:32 -08005228 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005229 TAG, "Setting persistence " + isPersistent + ": " + r);
5230
5231 if (isPersistent) {
5232 if (r.persistent) {
5233 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005234 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 return;
5236 }
5237 r.persistent = true;
5238 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005239 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 if (app.persistentActivities > 1) {
5241 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005242 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 return;
5244 }
5245 if (app.persistent) {
5246 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005247 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248 return;
5249 }
5250
5251 // App is now persistent... make sure it and the ones
5252 // following it now have the correct oom_adj.
5253 final long origId = Binder.clearCallingIdentity();
5254 updateOomAdjLocked();
5255 Binder.restoreCallingIdentity(origId);
5256
5257 } else {
5258 if (!r.persistent) {
5259 // Okay okay, I heard you already!
5260 return;
5261 }
5262 r.persistent = false;
5263 final long origId = Binder.clearCallingIdentity();
5264 decPersistentCountLocked(app);
5265 Binder.restoreCallingIdentity(origId);
5266
5267 }
5268 }
5269 }
5270
5271 public boolean clearApplicationUserData(final String packageName,
5272 final IPackageDataObserver observer) {
5273 int uid = Binder.getCallingUid();
5274 int pid = Binder.getCallingPid();
5275 long callingId = Binder.clearCallingIdentity();
5276 try {
5277 IPackageManager pm = ActivityThread.getPackageManager();
5278 int pkgUid = -1;
5279 synchronized(this) {
5280 try {
5281 pkgUid = pm.getPackageUid(packageName);
5282 } catch (RemoteException e) {
5283 }
5284 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005285 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005286 return false;
5287 }
5288 if (uid == pkgUid || checkComponentPermission(
5289 android.Manifest.permission.CLEAR_APP_USER_DATA,
5290 pid, uid, -1)
5291 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005292 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005293 } else {
5294 throw new SecurityException(pid+" does not have permission:"+
5295 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5296 "for process:"+packageName);
5297 }
5298 }
5299
5300 try {
5301 //clear application user data
5302 pm.clearApplicationUserData(packageName, observer);
5303 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5304 Uri.fromParts("package", packageName, null));
5305 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005306 synchronized (this) {
5307 broadcastIntentLocked(null, null, intent,
5308 null, null, 0, null, null, null,
5309 false, false, MY_PID, Process.SYSTEM_UID);
5310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 } catch (RemoteException e) {
5312 }
5313 } finally {
5314 Binder.restoreCallingIdentity(callingId);
5315 }
5316 return true;
5317 }
5318
Dianne Hackborn03abb812010-01-04 18:43:19 -08005319 public void killBackgroundProcesses(final String packageName) {
5320 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5321 != PackageManager.PERMISSION_GRANTED &&
5322 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5323 != PackageManager.PERMISSION_GRANTED) {
5324 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005325 + Binder.getCallingPid()
5326 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005327 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005328 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 throw new SecurityException(msg);
5330 }
5331
5332 long callingId = Binder.clearCallingIdentity();
5333 try {
5334 IPackageManager pm = ActivityThread.getPackageManager();
5335 int pkgUid = -1;
5336 synchronized(this) {
5337 try {
5338 pkgUid = pm.getPackageUid(packageName);
5339 } catch (RemoteException e) {
5340 }
5341 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005342 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 return;
5344 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005345 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005346 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005347 }
5348 } finally {
5349 Binder.restoreCallingIdentity(callingId);
5350 }
5351 }
5352
5353 public void forceStopPackage(final String packageName) {
5354 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5355 != PackageManager.PERMISSION_GRANTED) {
5356 String msg = "Permission Denial: forceStopPackage() from pid="
5357 + Binder.getCallingPid()
5358 + ", uid=" + Binder.getCallingUid()
5359 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005360 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005361 throw new SecurityException(msg);
5362 }
5363
5364 long callingId = Binder.clearCallingIdentity();
5365 try {
5366 IPackageManager pm = ActivityThread.getPackageManager();
5367 int pkgUid = -1;
5368 synchronized(this) {
5369 try {
5370 pkgUid = pm.getPackageUid(packageName);
5371 } catch (RemoteException e) {
5372 }
5373 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005374 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005375 return;
5376 }
5377 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005378 }
5379 } finally {
5380 Binder.restoreCallingIdentity(callingId);
5381 }
5382 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005383
5384 /*
5385 * The pkg name and uid have to be specified.
5386 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5387 */
5388 public void killApplicationWithUid(String pkg, int uid) {
5389 if (pkg == null) {
5390 return;
5391 }
5392 // Make sure the uid is valid.
5393 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005394 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005395 return;
5396 }
5397 int callerUid = Binder.getCallingUid();
5398 // Only the system server can kill an application
5399 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005400 // Post an aysnc message to kill the application
5401 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5402 msg.arg1 = uid;
5403 msg.arg2 = 0;
5404 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005405 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005406 } else {
5407 throw new SecurityException(callerUid + " cannot kill pkg: " +
5408 pkg);
5409 }
5410 }
5411
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005412 public void closeSystemDialogs(String reason) {
5413 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5414 if (reason != null) {
5415 intent.putExtra("reason", reason);
5416 }
5417
5418 final int uid = Binder.getCallingUid();
5419 final long origId = Binder.clearCallingIdentity();
5420 synchronized (this) {
5421 int i = mWatchers.beginBroadcast();
5422 while (i > 0) {
5423 i--;
5424 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5425 if (w != null) {
5426 try {
5427 w.closingSystemDialogs(reason);
5428 } catch (RemoteException e) {
5429 }
5430 }
5431 }
5432 mWatchers.finishBroadcast();
5433
Dianne Hackbornffa42482009-09-23 22:20:11 -07005434 mWindowManager.closeSystemDialogs(reason);
5435
5436 for (i=mHistory.size()-1; i>=0; i--) {
5437 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5438 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5439 finishActivityLocked(r, i,
5440 Activity.RESULT_CANCELED, null, "close-sys");
5441 }
5442 }
5443
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005444 broadcastIntentLocked(null, null, intent, null,
5445 null, 0, null, null, null, false, false, -1, uid);
5446 }
5447 Binder.restoreCallingIdentity(origId);
5448 }
5449
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005450 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005451 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005452 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5453 for (int i=pids.length-1; i>=0; i--) {
5454 infos[i] = new Debug.MemoryInfo();
5455 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005456 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005457 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005458 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005459
5460 public void killApplicationProcess(String processName, int uid) {
5461 if (processName == null) {
5462 return;
5463 }
5464
5465 int callerUid = Binder.getCallingUid();
5466 // Only the system server can kill an application
5467 if (callerUid == Process.SYSTEM_UID) {
5468 synchronized (this) {
5469 ProcessRecord app = getProcessRecordLocked(processName, uid);
5470 if (app != null) {
5471 try {
5472 app.thread.scheduleSuicide();
5473 } catch (RemoteException e) {
5474 // If the other end already died, then our work here is done.
5475 }
5476 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005477 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005478 + processName + " / " + uid);
5479 }
5480 }
5481 } else {
5482 throw new SecurityException(callerUid + " cannot kill app process: " +
5483 processName);
5484 }
5485 }
5486
Dianne Hackborn03abb812010-01-04 18:43:19 -08005487 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005488 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005489 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5490 Uri.fromParts("package", packageName, null));
5491 intent.putExtra(Intent.EXTRA_UID, uid);
5492 broadcastIntentLocked(null, null, intent,
5493 null, null, 0, null, null, null,
5494 false, false, MY_PID, Process.SYSTEM_UID);
5495 }
5496
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005497 private final boolean killPackageProcessesLocked(String packageName, int uid,
5498 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005499 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005500
Dianne Hackborn03abb812010-01-04 18:43:19 -08005501 // Remove all processes this package may have touched: all with the
5502 // same UID (except for the system or root user), and all whose name
5503 // matches the package name.
5504 final String procNamePrefix = packageName + ":";
5505 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5506 final int NA = apps.size();
5507 for (int ia=0; ia<NA; ia++) {
5508 ProcessRecord app = apps.valueAt(ia);
5509 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005510 if (doit) {
5511 procs.add(app);
5512 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005513 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5514 || app.processName.equals(packageName)
5515 || app.processName.startsWith(procNamePrefix)) {
5516 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005517 if (!doit) {
5518 return true;
5519 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005520 app.removed = true;
5521 procs.add(app);
5522 }
5523 }
5524 }
5525 }
5526
5527 int N = procs.size();
5528 for (int i=0; i<N; i++) {
5529 removeProcessLocked(procs.get(i), callerWillRestart);
5530 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005531 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005532 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005533
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005534 private final boolean forceStopPackageLocked(String name, int uid,
5535 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005536 int i, N;
5537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005538 if (uid < 0) {
5539 try {
5540 uid = ActivityThread.getPackageManager().getPackageUid(name);
5541 } catch (RemoteException e) {
5542 }
5543 }
5544
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005545 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005546 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005547
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005548 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5549 while (badApps.hasNext()) {
5550 SparseArray<Long> ba = badApps.next();
5551 if (ba.get(uid) != null) {
5552 badApps.remove();
5553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005554 }
5555 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005556
5557 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5558 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005559
5560 for (i=mHistory.size()-1; i>=0; i--) {
5561 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5562 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005563 if (!doit) {
5564 return true;
5565 }
5566 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005567 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005568 if (r.app != null) {
5569 r.app.removed = true;
5570 }
5571 r.app = null;
5572 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5573 }
5574 }
5575
5576 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5577 for (ServiceRecord service : mServices.values()) {
5578 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005579 if (!doit) {
5580 return true;
5581 }
5582 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005583 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005584 if (service.app != null) {
5585 service.app.removed = true;
5586 }
5587 service.app = null;
5588 services.add(service);
5589 }
5590 }
5591
5592 N = services.size();
5593 for (i=0; i<N; i++) {
5594 bringDownServiceLocked(services.get(i), true);
5595 }
5596
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005597 if (doit) {
5598 if (purgeCache) {
5599 AttributeCache ac = AttributeCache.instance();
5600 if (ac != null) {
5601 ac.removePackage(name);
5602 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005603 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005604 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005605 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005606
5607 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005608 }
5609
5610 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5611 final String name = app.processName;
5612 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005613 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005614 TAG, "Force removing process " + app + " (" + name
5615 + "/" + uid + ")");
5616
5617 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005618 if (mHeavyWeightProcess == app) {
5619 mHeavyWeightProcess = null;
5620 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5621 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 boolean needRestart = false;
5623 if (app.pid > 0 && app.pid != MY_PID) {
5624 int pid = app.pid;
5625 synchronized (mPidsSelfLocked) {
5626 mPidsSelfLocked.remove(pid);
5627 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5628 }
5629 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005630 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 Process.killProcess(pid);
5632
5633 if (app.persistent) {
5634 if (!callerWillRestart) {
5635 addAppLocked(app.info);
5636 } else {
5637 needRestart = true;
5638 }
5639 }
5640 } else {
5641 mRemovedProcesses.add(app);
5642 }
5643
5644 return needRestart;
5645 }
5646
5647 private final void processStartTimedOutLocked(ProcessRecord app) {
5648 final int pid = app.pid;
5649 boolean gone = false;
5650 synchronized (mPidsSelfLocked) {
5651 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5652 if (knownApp != null && knownApp.thread == null) {
5653 mPidsSelfLocked.remove(pid);
5654 gone = true;
5655 }
5656 }
5657
5658 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005659 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005660 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005661 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005662 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005663 if (mHeavyWeightProcess == app) {
5664 mHeavyWeightProcess = null;
5665 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5666 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005667 // Take care of any launching providers waiting for this process.
5668 checkAppInLaunchingProvidersLocked(app, true);
5669 // Take care of any services that are waiting for the process.
5670 for (int i=0; i<mPendingServices.size(); i++) {
5671 ServiceRecord sr = mPendingServices.get(i);
5672 if (app.info.uid == sr.appInfo.uid
5673 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005674 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005675 mPendingServices.remove(i);
5676 i--;
5677 bringDownServiceLocked(sr, true);
5678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005680 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005681 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005682 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005683 try {
5684 IBackupManager bm = IBackupManager.Stub.asInterface(
5685 ServiceManager.getService(Context.BACKUP_SERVICE));
5686 bm.agentDisconnected(app.info.packageName);
5687 } catch (RemoteException e) {
5688 // Can't happen; the backup manager is local
5689 }
5690 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005691 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005692 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005693 mPendingBroadcast = null;
5694 scheduleBroadcastsLocked();
5695 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005696 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005697 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005698 }
5699 }
5700
5701 private final boolean attachApplicationLocked(IApplicationThread thread,
5702 int pid) {
5703
5704 // Find the application record that is being attached... either via
5705 // the pid if we are running in multiple processes, or just pull the
5706 // next app record if we are emulating process with anonymous threads.
5707 ProcessRecord app;
5708 if (pid != MY_PID && pid >= 0) {
5709 synchronized (mPidsSelfLocked) {
5710 app = mPidsSelfLocked.get(pid);
5711 }
5712 } else if (mStartingProcesses.size() > 0) {
5713 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005714 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005715 } else {
5716 app = null;
5717 }
5718
5719 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005720 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005721 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005722 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005723 if (pid > 0 && pid != MY_PID) {
5724 Process.killProcess(pid);
5725 } else {
5726 try {
5727 thread.scheduleExit();
5728 } catch (Exception e) {
5729 // Ignore exceptions.
5730 }
5731 }
5732 return false;
5733 }
5734
5735 // If this application record is still attached to a previous
5736 // process, clean it up now.
5737 if (app.thread != null) {
5738 handleAppDiedLocked(app, true);
5739 }
5740
5741 // Tell the process all about itself.
5742
Joe Onorato8a9b2202010-02-26 18:56:32 -08005743 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005744 TAG, "Binding process pid " + pid + " to record " + app);
5745
5746 String processName = app.processName;
5747 try {
5748 thread.asBinder().linkToDeath(new AppDeathRecipient(
5749 app, pid, thread), 0);
5750 } catch (RemoteException e) {
5751 app.resetPackageList();
5752 startProcessLocked(app, "link fail", processName);
5753 return false;
5754 }
5755
Doug Zongker2bec3d42009-12-04 12:52:44 -08005756 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005757
5758 app.thread = thread;
5759 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005760 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5761 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005762 app.forcingToForeground = null;
5763 app.foregroundServices = false;
5764 app.debugging = false;
5765
5766 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5767
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005768 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5769 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005770
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005771 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005772 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005773 }
5774
Joe Onorato8a9b2202010-02-26 18:56:32 -08005775 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005776 TAG, "New app record " + app
5777 + " thread=" + thread.asBinder() + " pid=" + pid);
5778 try {
5779 int testMode = IApplicationThread.DEBUG_OFF;
5780 if (mDebugApp != null && mDebugApp.equals(processName)) {
5781 testMode = mWaitForDebugger
5782 ? IApplicationThread.DEBUG_WAIT
5783 : IApplicationThread.DEBUG_ON;
5784 app.debugging = true;
5785 if (mDebugTransient) {
5786 mDebugApp = mOrigDebugApp;
5787 mWaitForDebugger = mOrigWaitForDebugger;
5788 }
5789 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005790
Christopher Tate181fafa2009-05-14 11:12:14 -07005791 // If the app is being launched for restore or full backup, set it up specially
5792 boolean isRestrictedBackupMode = false;
5793 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5794 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5795 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5796 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005797
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005798 ensurePackageDexOpt(app.instrumentationInfo != null
5799 ? app.instrumentationInfo.packageName
5800 : app.info.packageName);
5801 if (app.instrumentationClass != null) {
5802 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005803 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005804 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005805 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005806 thread.bindApplication(processName, app.instrumentationInfo != null
5807 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005808 app.instrumentationClass, app.instrumentationProfileFile,
5809 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005810 isRestrictedBackupMode || !normalMode,
5811 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005812 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005813 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005814 } catch (Exception e) {
5815 // todo: Yikes! What should we do? For now we will try to
5816 // start another process, but that could easily get us in
5817 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005818 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005819
5820 app.resetPackageList();
5821 startProcessLocked(app, "bind fail", processName);
5822 return false;
5823 }
5824
5825 // Remove this record from the list of starting applications.
5826 mPersistentStartingProcesses.remove(app);
5827 mProcessesOnHold.remove(app);
5828
5829 boolean badApp = false;
5830 boolean didSomething = false;
5831
5832 // See if the top visible activity is waiting to run in this process...
5833 HistoryRecord hr = topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07005834 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005835 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5836 && processName.equals(hr.processName)) {
5837 try {
5838 if (realStartActivityLocked(hr, app, true, true)) {
5839 didSomething = true;
5840 }
5841 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005842 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005843 + hr.intent.getComponent().flattenToShortString(), e);
5844 badApp = true;
5845 }
5846 } else {
5847 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5848 }
5849 }
5850
5851 // Find any services that should be running in this process...
5852 if (!badApp && mPendingServices.size() > 0) {
5853 ServiceRecord sr = null;
5854 try {
5855 for (int i=0; i<mPendingServices.size(); i++) {
5856 sr = mPendingServices.get(i);
5857 if (app.info.uid != sr.appInfo.uid
5858 || !processName.equals(sr.processName)) {
5859 continue;
5860 }
5861
5862 mPendingServices.remove(i);
5863 i--;
5864 realStartServiceLocked(sr, app);
5865 didSomething = true;
5866 }
5867 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005868 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005869 + sr.shortName, e);
5870 badApp = true;
5871 }
5872 }
5873
5874 // Check if the next broadcast receiver is in this process...
5875 BroadcastRecord br = mPendingBroadcast;
5876 if (!badApp && br != null && br.curApp == app) {
5877 try {
5878 mPendingBroadcast = null;
5879 processCurBroadcastLocked(br, app);
5880 didSomething = true;
5881 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005882 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005883 + br.curComponent.flattenToShortString(), e);
5884 badApp = true;
5885 logBroadcastReceiverDiscard(br);
5886 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5887 br.resultExtras, br.resultAbort, true);
5888 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005889 // We need to reset the state if we fails to start the receiver.
5890 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005891 }
5892 }
5893
Christopher Tate181fafa2009-05-14 11:12:14 -07005894 // Check whether the next backup agent is in this process...
5895 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005896 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005897 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005898 try {
5899 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5900 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005901 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005902 e.printStackTrace();
5903 }
5904 }
5905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005906 if (badApp) {
5907 // todo: Also need to kill application to deal with all
5908 // kinds of exceptions.
5909 handleAppDiedLocked(app, false);
5910 return false;
5911 }
5912
5913 if (!didSomething) {
5914 updateOomAdjLocked();
5915 }
5916
5917 return true;
5918 }
5919
5920 public final void attachApplication(IApplicationThread thread) {
5921 synchronized (this) {
5922 int callingPid = Binder.getCallingPid();
5923 final long origId = Binder.clearCallingIdentity();
5924 attachApplicationLocked(thread, callingPid);
5925 Binder.restoreCallingIdentity(origId);
5926 }
5927 }
5928
Dianne Hackborne88846e2009-09-30 21:34:25 -07005929 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005930 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005931 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005932 Binder.restoreCallingIdentity(origId);
5933 }
5934
5935 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5936 boolean remove) {
5937 int N = mStoppingActivities.size();
5938 if (N <= 0) return null;
5939
5940 ArrayList<HistoryRecord> stops = null;
5941
5942 final boolean nowVisible = mResumedActivity != null
5943 && mResumedActivity.nowVisible
5944 && !mResumedActivity.waitingVisible;
5945 for (int i=0; i<N; i++) {
5946 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005947 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005948 + nowVisible + " waitingVisible=" + s.waitingVisible
5949 + " finishing=" + s.finishing);
5950 if (s.waitingVisible && nowVisible) {
5951 mWaitingVisibleActivities.remove(s);
5952 s.waitingVisible = false;
5953 if (s.finishing) {
5954 // If this activity is finishing, it is sitting on top of
5955 // everyone else but we now know it is no longer needed...
5956 // so get rid of it. Otherwise, we need to go through the
5957 // normal flow and hide it once we determine that it is
5958 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005959 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 mWindowManager.setAppVisibility(s, false);
5961 }
5962 }
5963 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005964 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005965 if (stops == null) {
5966 stops = new ArrayList<HistoryRecord>();
5967 }
5968 stops.add(s);
5969 mStoppingActivities.remove(i);
5970 N--;
5971 i--;
5972 }
5973 }
5974
5975 return stops;
5976 }
5977
5978 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005979 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005980 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005981 mWindowManager.enableScreenAfterBoot();
5982 }
5983
Dianne Hackborne88846e2009-09-30 21:34:25 -07005984 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5985 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005986 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005987
5988 ArrayList<HistoryRecord> stops = null;
5989 ArrayList<HistoryRecord> finishes = null;
5990 ArrayList<HistoryRecord> thumbnails = null;
5991 int NS = 0;
5992 int NF = 0;
5993 int NT = 0;
5994 IApplicationThread sendThumbnail = null;
5995 boolean booting = false;
5996 boolean enableScreen = false;
5997
5998 synchronized (this) {
5999 if (token != null) {
6000 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
6001 }
6002
6003 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07006004 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006005 if (index >= 0) {
6006 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6007
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006008 if (fromTimeout) {
6009 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
6010 }
6011
Dianne Hackborne88846e2009-09-30 21:34:25 -07006012 // This is a hack to semi-deal with a race condition
6013 // in the client where it can be constructed with a
6014 // newer configuration from when we asked it to launch.
6015 // We'll update with whatever configuration it now says
6016 // it used to launch.
6017 if (config != null) {
6018 r.configuration = config;
6019 }
6020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006021 // No longer need to keep the device awake.
6022 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
6023 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
6024 mLaunchingActivity.release();
6025 }
6026
6027 // We are now idle. If someone is waiting for a thumbnail from
6028 // us, we can now deliver.
6029 r.idle = true;
6030 scheduleAppGcsLocked();
6031 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
6032 sendThumbnail = r.app.thread;
6033 r.thumbnailNeeded = false;
6034 }
6035
6036 // If this activity is fullscreen, set up to hide those under it.
6037
Joe Onorato8a9b2202010-02-26 18:56:32 -08006038 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006039 ensureActivitiesVisibleLocked(null, 0);
6040
Joe Onorato8a9b2202010-02-26 18:56:32 -08006041 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 if (!mBooted && !fromTimeout) {
6043 mBooted = true;
6044 enableScreen = true;
6045 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006046
6047 } else if (fromTimeout) {
6048 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006049 }
6050
6051 // Atomically retrieve all of the other things to do.
6052 stops = processStoppingActivitiesLocked(true);
6053 NS = stops != null ? stops.size() : 0;
6054 if ((NF=mFinishingActivities.size()) > 0) {
6055 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
6056 mFinishingActivities.clear();
6057 }
6058 if ((NT=mCancelledThumbnails.size()) > 0) {
6059 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
6060 mCancelledThumbnails.clear();
6061 }
6062
6063 booting = mBooting;
6064 mBooting = false;
6065 }
6066
6067 int i;
6068
6069 // Send thumbnail if requested.
6070 if (sendThumbnail != null) {
6071 try {
6072 sendThumbnail.requestThumbnail(token);
6073 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006074 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006075 sendPendingThumbnail(null, token, null, null, true);
6076 }
6077 }
6078
6079 // Stop any activities that are scheduled to do so but have been
6080 // waiting for the next one to start.
6081 for (i=0; i<NS; i++) {
6082 HistoryRecord r = (HistoryRecord)stops.get(i);
6083 synchronized (this) {
6084 if (r.finishing) {
6085 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
6086 } else {
6087 stopActivityLocked(r);
6088 }
6089 }
6090 }
6091
6092 // Finish any activities that are scheduled to do so but have been
6093 // waiting for the next one to start.
6094 for (i=0; i<NF; i++) {
6095 HistoryRecord r = (HistoryRecord)finishes.get(i);
6096 synchronized (this) {
6097 destroyActivityLocked(r, true);
6098 }
6099 }
6100
6101 // Report back to any thumbnail receivers.
6102 for (i=0; i<NT; i++) {
6103 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
6104 sendPendingThumbnail(r, null, null, null, true);
6105 }
6106
6107 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006108 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006109 }
6110
6111 trimApplications();
6112 //dump();
6113 //mWindowManager.dump();
6114
6115 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006116 enableScreenAfterBoot();
6117 }
6118 }
6119
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006120 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006121 IntentFilter pkgFilter = new IntentFilter();
6122 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
6123 pkgFilter.addDataScheme("package");
6124 mContext.registerReceiver(new BroadcastReceiver() {
6125 @Override
6126 public void onReceive(Context context, Intent intent) {
6127 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
6128 if (pkgs != null) {
6129 for (String pkg : pkgs) {
6130 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
6131 setResultCode(Activity.RESULT_OK);
6132 return;
6133 }
6134 }
6135 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006136 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006137 }, pkgFilter);
6138
6139 synchronized (this) {
6140 // Ensure that any processes we had put on hold are now started
6141 // up.
6142 final int NP = mProcessesOnHold.size();
6143 if (NP > 0) {
6144 ArrayList<ProcessRecord> procs =
6145 new ArrayList<ProcessRecord>(mProcessesOnHold);
6146 for (int ip=0; ip<NP; ip++) {
6147 this.startProcessLocked(procs.get(ip), "on-hold", null);
6148 }
6149 }
6150
6151 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6152 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006153 broadcastIntentLocked(null, null,
6154 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
6155 null, null, 0, null, null,
6156 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
6157 false, false, MY_PID, Process.SYSTEM_UID);
6158 }
6159 }
6160 }
6161
6162 final void ensureBootCompleted() {
6163 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006164 boolean enableScreen;
6165 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006166 booting = mBooting;
6167 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006168 enableScreen = !mBooted;
6169 mBooted = true;
6170 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006171
6172 if (booting) {
6173 finishBooting();
6174 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006175
6176 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006177 enableScreenAfterBoot();
6178 }
6179 }
6180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006181 public final void activityPaused(IBinder token, Bundle icicle) {
6182 // Refuse possible leaked file descriptors
6183 if (icicle != null && icicle.hasFileDescriptors()) {
6184 throw new IllegalArgumentException("File descriptors passed in Bundle");
6185 }
6186
6187 final long origId = Binder.clearCallingIdentity();
6188 activityPaused(token, icicle, false);
6189 Binder.restoreCallingIdentity(origId);
6190 }
6191
6192 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006193 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006194 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
6195 + ", timeout=" + timeout);
6196
6197 HistoryRecord r = null;
6198
6199 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006200 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006201 if (index >= 0) {
6202 r = (HistoryRecord)mHistory.get(index);
6203 if (!timeout) {
6204 r.icicle = icicle;
6205 r.haveState = true;
6206 }
6207 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
6208 if (mPausingActivity == r) {
6209 r.state = ActivityState.PAUSED;
6210 completePauseLocked();
6211 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08006212 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006213 System.identityHashCode(r), r.shortComponentName,
6214 mPausingActivity != null
6215 ? mPausingActivity.shortComponentName : "(none)");
6216 }
6217 }
6218 }
6219 }
6220
6221 public final void activityStopped(IBinder token, Bitmap thumbnail,
6222 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006223 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006224 TAG, "Activity stopped: token=" + token);
6225
6226 HistoryRecord r = null;
6227
6228 final long origId = Binder.clearCallingIdentity();
6229
6230 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006231 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006232 if (index >= 0) {
6233 r = (HistoryRecord)mHistory.get(index);
6234 r.thumbnail = thumbnail;
6235 r.description = description;
6236 r.stopped = true;
6237 r.state = ActivityState.STOPPED;
6238 if (!r.finishing) {
6239 if (r.configDestroy) {
6240 destroyActivityLocked(r, true);
6241 resumeTopActivityLocked(null);
6242 }
6243 }
6244 }
6245 }
6246
6247 if (r != null) {
6248 sendPendingThumbnail(r, null, null, null, false);
6249 }
6250
6251 trimApplications();
6252
6253 Binder.restoreCallingIdentity(origId);
6254 }
6255
6256 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006257 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006258 synchronized (this) {
6259 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
6260
Dianne Hackborn75b03852009-06-12 15:43:26 -07006261 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006262 if (index >= 0) {
6263 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6264 if (r.state == ActivityState.DESTROYING) {
6265 final long origId = Binder.clearCallingIdentity();
6266 removeActivityFromHistoryLocked(r);
6267 Binder.restoreCallingIdentity(origId);
6268 }
6269 }
6270 }
6271 }
6272
6273 public String getCallingPackage(IBinder token) {
6274 synchronized (this) {
6275 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07006276 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006277 }
6278 }
6279
6280 public ComponentName getCallingActivity(IBinder token) {
6281 synchronized (this) {
6282 HistoryRecord r = getCallingRecordLocked(token);
6283 return r != null ? r.intent.getComponent() : null;
6284 }
6285 }
6286
6287 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006288 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289 if (index >= 0) {
6290 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6291 if (r != null) {
6292 return r.resultTo;
6293 }
6294 }
6295 return null;
6296 }
6297
6298 public ComponentName getActivityClassForToken(IBinder token) {
6299 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006300 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006301 if (index >= 0) {
6302 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6303 return r.intent.getComponent();
6304 }
6305 return null;
6306 }
6307 }
6308
6309 public String getPackageForToken(IBinder token) {
6310 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006311 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006312 if (index >= 0) {
6313 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6314 return r.packageName;
6315 }
6316 return null;
6317 }
6318 }
6319
6320 public IIntentSender getIntentSender(int type,
6321 String packageName, IBinder token, String resultWho,
6322 int requestCode, Intent intent, String resolvedType, int flags) {
6323 // Refuse possible leaked file descriptors
6324 if (intent != null && intent.hasFileDescriptors() == true) {
6325 throw new IllegalArgumentException("File descriptors passed in Intent");
6326 }
6327
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006328 if (type == INTENT_SENDER_BROADCAST) {
6329 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6330 throw new IllegalArgumentException(
6331 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6332 }
6333 }
6334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006335 synchronized(this) {
6336 int callingUid = Binder.getCallingUid();
6337 try {
6338 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6339 Process.supportsProcesses()) {
6340 int uid = ActivityThread.getPackageManager()
6341 .getPackageUid(packageName);
6342 if (uid != Binder.getCallingUid()) {
6343 String msg = "Permission Denial: getIntentSender() from pid="
6344 + Binder.getCallingPid()
6345 + ", uid=" + Binder.getCallingUid()
6346 + ", (need uid=" + uid + ")"
6347 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006348 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006349 throw new SecurityException(msg);
6350 }
6351 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006352
6353 return getIntentSenderLocked(type, packageName, callingUid,
6354 token, resultWho, requestCode, intent, resolvedType, flags);
6355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 } catch (RemoteException e) {
6357 throw new SecurityException(e);
6358 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006359 }
6360 }
6361
6362 IIntentSender getIntentSenderLocked(int type,
6363 String packageName, int callingUid, IBinder token, String resultWho,
6364 int requestCode, Intent intent, String resolvedType, int flags) {
6365 HistoryRecord activity = null;
6366 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6367 int index = indexOfTokenLocked(token);
6368 if (index < 0) {
6369 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006370 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006371 activity = (HistoryRecord)mHistory.get(index);
6372 if (activity.finishing) {
6373 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006375 }
6376
6377 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6378 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6379 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6380 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6381 |PendingIntent.FLAG_UPDATE_CURRENT);
6382
6383 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6384 type, packageName, activity, resultWho,
6385 requestCode, intent, resolvedType, flags);
6386 WeakReference<PendingIntentRecord> ref;
6387 ref = mIntentSenderRecords.get(key);
6388 PendingIntentRecord rec = ref != null ? ref.get() : null;
6389 if (rec != null) {
6390 if (!cancelCurrent) {
6391 if (updateCurrent) {
6392 rec.key.requestIntent.replaceExtras(intent);
6393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006394 return rec;
6395 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006396 rec.canceled = true;
6397 mIntentSenderRecords.remove(key);
6398 }
6399 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006400 return rec;
6401 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006402 rec = new PendingIntentRecord(this, key, callingUid);
6403 mIntentSenderRecords.put(key, rec.ref);
6404 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6405 if (activity.pendingResults == null) {
6406 activity.pendingResults
6407 = new HashSet<WeakReference<PendingIntentRecord>>();
6408 }
6409 activity.pendingResults.add(rec.ref);
6410 }
6411 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006412 }
6413
6414 public void cancelIntentSender(IIntentSender sender) {
6415 if (!(sender instanceof PendingIntentRecord)) {
6416 return;
6417 }
6418 synchronized(this) {
6419 PendingIntentRecord rec = (PendingIntentRecord)sender;
6420 try {
6421 int uid = ActivityThread.getPackageManager()
6422 .getPackageUid(rec.key.packageName);
6423 if (uid != Binder.getCallingUid()) {
6424 String msg = "Permission Denial: cancelIntentSender() from pid="
6425 + Binder.getCallingPid()
6426 + ", uid=" + Binder.getCallingUid()
6427 + " is not allowed to cancel packges "
6428 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006429 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006430 throw new SecurityException(msg);
6431 }
6432 } catch (RemoteException e) {
6433 throw new SecurityException(e);
6434 }
6435 cancelIntentSenderLocked(rec, true);
6436 }
6437 }
6438
6439 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6440 rec.canceled = true;
6441 mIntentSenderRecords.remove(rec.key);
6442 if (cleanActivity && rec.key.activity != null) {
6443 rec.key.activity.pendingResults.remove(rec.ref);
6444 }
6445 }
6446
6447 public String getPackageForIntentSender(IIntentSender pendingResult) {
6448 if (!(pendingResult instanceof PendingIntentRecord)) {
6449 return null;
6450 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006451 try {
6452 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6453 return res.key.packageName;
6454 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006455 }
6456 return null;
6457 }
6458
6459 public void setProcessLimit(int max) {
6460 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6461 "setProcessLimit()");
6462 mProcessLimit = max;
6463 }
6464
6465 public int getProcessLimit() {
6466 return mProcessLimit;
6467 }
6468
6469 void foregroundTokenDied(ForegroundToken token) {
6470 synchronized (ActivityManagerService.this) {
6471 synchronized (mPidsSelfLocked) {
6472 ForegroundToken cur
6473 = mForegroundProcesses.get(token.pid);
6474 if (cur != token) {
6475 return;
6476 }
6477 mForegroundProcesses.remove(token.pid);
6478 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6479 if (pr == null) {
6480 return;
6481 }
6482 pr.forcingToForeground = null;
6483 pr.foregroundServices = false;
6484 }
6485 updateOomAdjLocked();
6486 }
6487 }
6488
6489 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6490 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6491 "setProcessForeground()");
6492 synchronized(this) {
6493 boolean changed = false;
6494
6495 synchronized (mPidsSelfLocked) {
6496 ProcessRecord pr = mPidsSelfLocked.get(pid);
6497 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006498 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006499 return;
6500 }
6501 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6502 if (oldToken != null) {
6503 oldToken.token.unlinkToDeath(oldToken, 0);
6504 mForegroundProcesses.remove(pid);
6505 pr.forcingToForeground = null;
6506 changed = true;
6507 }
6508 if (isForeground && token != null) {
6509 ForegroundToken newToken = new ForegroundToken() {
6510 public void binderDied() {
6511 foregroundTokenDied(this);
6512 }
6513 };
6514 newToken.pid = pid;
6515 newToken.token = token;
6516 try {
6517 token.linkToDeath(newToken, 0);
6518 mForegroundProcesses.put(pid, newToken);
6519 pr.forcingToForeground = token;
6520 changed = true;
6521 } catch (RemoteException e) {
6522 // If the process died while doing this, we will later
6523 // do the cleanup with the process death link.
6524 }
6525 }
6526 }
6527
6528 if (changed) {
6529 updateOomAdjLocked();
6530 }
6531 }
6532 }
6533
6534 // =========================================================
6535 // PERMISSIONS
6536 // =========================================================
6537
6538 static class PermissionController extends IPermissionController.Stub {
6539 ActivityManagerService mActivityManagerService;
6540 PermissionController(ActivityManagerService activityManagerService) {
6541 mActivityManagerService = activityManagerService;
6542 }
6543
6544 public boolean checkPermission(String permission, int pid, int uid) {
6545 return mActivityManagerService.checkPermission(permission, pid,
6546 uid) == PackageManager.PERMISSION_GRANTED;
6547 }
6548 }
6549
6550 /**
6551 * This can be called with or without the global lock held.
6552 */
6553 int checkComponentPermission(String permission, int pid, int uid,
6554 int reqUid) {
6555 // We might be performing an operation on behalf of an indirect binder
6556 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6557 // client identity accordingly before proceeding.
6558 Identity tlsIdentity = sCallerIdentity.get();
6559 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006560 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006561 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6562 uid = tlsIdentity.uid;
6563 pid = tlsIdentity.pid;
6564 }
6565
6566 // Root, system server and our own process get to do everything.
6567 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6568 !Process.supportsProcesses()) {
6569 return PackageManager.PERMISSION_GRANTED;
6570 }
6571 // If the target requires a specific UID, always fail for others.
6572 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006573 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006574 return PackageManager.PERMISSION_DENIED;
6575 }
6576 if (permission == null) {
6577 return PackageManager.PERMISSION_GRANTED;
6578 }
6579 try {
6580 return ActivityThread.getPackageManager()
6581 .checkUidPermission(permission, uid);
6582 } catch (RemoteException e) {
6583 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006584 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006585 }
6586 return PackageManager.PERMISSION_DENIED;
6587 }
6588
6589 /**
6590 * As the only public entry point for permissions checking, this method
6591 * can enforce the semantic that requesting a check on a null global
6592 * permission is automatically denied. (Internally a null permission
6593 * string is used when calling {@link #checkComponentPermission} in cases
6594 * when only uid-based security is needed.)
6595 *
6596 * This can be called with or without the global lock held.
6597 */
6598 public int checkPermission(String permission, int pid, int uid) {
6599 if (permission == null) {
6600 return PackageManager.PERMISSION_DENIED;
6601 }
6602 return checkComponentPermission(permission, pid, uid, -1);
6603 }
6604
6605 /**
6606 * Binder IPC calls go through the public entry point.
6607 * This can be called with or without the global lock held.
6608 */
6609 int checkCallingPermission(String permission) {
6610 return checkPermission(permission,
6611 Binder.getCallingPid(),
6612 Binder.getCallingUid());
6613 }
6614
6615 /**
6616 * This can be called with or without the global lock held.
6617 */
6618 void enforceCallingPermission(String permission, String func) {
6619 if (checkCallingPermission(permission)
6620 == PackageManager.PERMISSION_GRANTED) {
6621 return;
6622 }
6623
6624 String msg = "Permission Denial: " + func + " from pid="
6625 + Binder.getCallingPid()
6626 + ", uid=" + Binder.getCallingUid()
6627 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006628 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006629 throw new SecurityException(msg);
6630 }
6631
6632 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6633 ProviderInfo pi, int uid, int modeFlags) {
6634 try {
6635 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6636 if ((pi.readPermission != null) &&
6637 (pm.checkUidPermission(pi.readPermission, uid)
6638 != PackageManager.PERMISSION_GRANTED)) {
6639 return false;
6640 }
6641 }
6642 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6643 if ((pi.writePermission != null) &&
6644 (pm.checkUidPermission(pi.writePermission, uid)
6645 != PackageManager.PERMISSION_GRANTED)) {
6646 return false;
6647 }
6648 }
6649 return true;
6650 } catch (RemoteException e) {
6651 return false;
6652 }
6653 }
6654
6655 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6656 int modeFlags) {
6657 // Root gets to do everything.
6658 if (uid == 0 || !Process.supportsProcesses()) {
6659 return true;
6660 }
6661 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6662 if (perms == null) return false;
6663 UriPermission perm = perms.get(uri);
6664 if (perm == null) return false;
6665 return (modeFlags&perm.modeFlags) == modeFlags;
6666 }
6667
6668 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6669 // Another redirected-binder-call permissions check as in
6670 // {@link checkComponentPermission}.
6671 Identity tlsIdentity = sCallerIdentity.get();
6672 if (tlsIdentity != null) {
6673 uid = tlsIdentity.uid;
6674 pid = tlsIdentity.pid;
6675 }
6676
6677 // Our own process gets to do everything.
6678 if (pid == MY_PID) {
6679 return PackageManager.PERMISSION_GRANTED;
6680 }
6681 synchronized(this) {
6682 return checkUriPermissionLocked(uri, uid, modeFlags)
6683 ? PackageManager.PERMISSION_GRANTED
6684 : PackageManager.PERMISSION_DENIED;
6685 }
6686 }
6687
6688 private void grantUriPermissionLocked(int callingUid,
6689 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6690 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6691 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6692 if (modeFlags == 0) {
6693 return;
6694 }
6695
Joe Onorato8a9b2202010-02-26 18:56:32 -08006696 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006697 "Requested grant " + targetPkg + " permission to " + uri);
6698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699 final IPackageManager pm = ActivityThread.getPackageManager();
6700
6701 // If this is not a content: uri, we can't do anything with it.
6702 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006703 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006704 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 return;
6706 }
6707
6708 String name = uri.getAuthority();
6709 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006710 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006711 if (cpr != null) {
6712 pi = cpr.info;
6713 } else {
6714 try {
6715 pi = pm.resolveContentProvider(name,
6716 PackageManager.GET_URI_PERMISSION_PATTERNS);
6717 } catch (RemoteException ex) {
6718 }
6719 }
6720 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006721 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006722 return;
6723 }
6724
6725 int targetUid;
6726 try {
6727 targetUid = pm.getPackageUid(targetPkg);
6728 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006729 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006730 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006731 return;
6732 }
6733 } catch (RemoteException ex) {
6734 return;
6735 }
6736
6737 // First... does the target actually need this permission?
6738 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6739 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006740 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006741 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006742 return;
6743 }
6744
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006745 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006746 if (!pi.grantUriPermissions) {
6747 throw new SecurityException("Provider " + pi.packageName
6748 + "/" + pi.name
6749 + " does not allow granting of Uri permissions (uri "
6750 + uri + ")");
6751 }
6752 if (pi.uriPermissionPatterns != null) {
6753 final int N = pi.uriPermissionPatterns.length;
6754 boolean allowed = false;
6755 for (int i=0; i<N; i++) {
6756 if (pi.uriPermissionPatterns[i] != null
6757 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6758 allowed = true;
6759 break;
6760 }
6761 }
6762 if (!allowed) {
6763 throw new SecurityException("Provider " + pi.packageName
6764 + "/" + pi.name
6765 + " does not allow granting of permission to path of Uri "
6766 + uri);
6767 }
6768 }
6769
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006770 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006771 // this uri?
6772 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6773 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6774 throw new SecurityException("Uid " + callingUid
6775 + " does not have permission to uri " + uri);
6776 }
6777 }
6778
6779 // Okay! So here we are: the caller has the assumed permission
6780 // to the uri, and the target doesn't. Let's now give this to
6781 // the target.
6782
Joe Onorato8a9b2202010-02-26 18:56:32 -08006783 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006784 "Granting " + targetPkg + " permission to " + uri);
6785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006786 HashMap<Uri, UriPermission> targetUris
6787 = mGrantedUriPermissions.get(targetUid);
6788 if (targetUris == null) {
6789 targetUris = new HashMap<Uri, UriPermission>();
6790 mGrantedUriPermissions.put(targetUid, targetUris);
6791 }
6792
6793 UriPermission perm = targetUris.get(uri);
6794 if (perm == null) {
6795 perm = new UriPermission(targetUid, uri);
6796 targetUris.put(uri, perm);
6797
6798 }
6799 perm.modeFlags |= modeFlags;
6800 if (activity == null) {
6801 perm.globalModeFlags |= modeFlags;
6802 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6803 perm.readActivities.add(activity);
6804 if (activity.readUriPermissions == null) {
6805 activity.readUriPermissions = new HashSet<UriPermission>();
6806 }
6807 activity.readUriPermissions.add(perm);
6808 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6809 perm.writeActivities.add(activity);
6810 if (activity.writeUriPermissions == null) {
6811 activity.writeUriPermissions = new HashSet<UriPermission>();
6812 }
6813 activity.writeUriPermissions.add(perm);
6814 }
6815 }
6816
6817 private void grantUriPermissionFromIntentLocked(int callingUid,
6818 String targetPkg, Intent intent, HistoryRecord activity) {
6819 if (intent == null) {
6820 return;
6821 }
6822 Uri data = intent.getData();
6823 if (data == null) {
6824 return;
6825 }
6826 grantUriPermissionLocked(callingUid, targetPkg, data,
6827 intent.getFlags(), activity);
6828 }
6829
6830 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6831 Uri uri, int modeFlags) {
6832 synchronized(this) {
6833 final ProcessRecord r = getRecordForAppLocked(caller);
6834 if (r == null) {
6835 throw new SecurityException("Unable to find app for caller "
6836 + caller
6837 + " when granting permission to uri " + uri);
6838 }
6839 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006840 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006841 return;
6842 }
6843 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006844 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006845 return;
6846 }
6847
6848 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6849 null);
6850 }
6851 }
6852
6853 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6854 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6855 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6856 HashMap<Uri, UriPermission> perms
6857 = mGrantedUriPermissions.get(perm.uid);
6858 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006859 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006860 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006861 perms.remove(perm.uri);
6862 if (perms.size() == 0) {
6863 mGrantedUriPermissions.remove(perm.uid);
6864 }
6865 }
6866 }
6867 }
6868
6869 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6870 if (activity.readUriPermissions != null) {
6871 for (UriPermission perm : activity.readUriPermissions) {
6872 perm.readActivities.remove(activity);
6873 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6874 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6875 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6876 removeUriPermissionIfNeededLocked(perm);
6877 }
6878 }
6879 }
6880 if (activity.writeUriPermissions != null) {
6881 for (UriPermission perm : activity.writeUriPermissions) {
6882 perm.writeActivities.remove(activity);
6883 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6884 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6885 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6886 removeUriPermissionIfNeededLocked(perm);
6887 }
6888 }
6889 }
6890 }
6891
6892 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6893 int modeFlags) {
6894 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6895 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6896 if (modeFlags == 0) {
6897 return;
6898 }
6899
Joe Onorato8a9b2202010-02-26 18:56:32 -08006900 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006901 "Revoking all granted permissions to " + uri);
6902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006903 final IPackageManager pm = ActivityThread.getPackageManager();
6904
6905 final String authority = uri.getAuthority();
6906 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006907 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006908 if (cpr != null) {
6909 pi = cpr.info;
6910 } else {
6911 try {
6912 pi = pm.resolveContentProvider(authority,
6913 PackageManager.GET_URI_PERMISSION_PATTERNS);
6914 } catch (RemoteException ex) {
6915 }
6916 }
6917 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006918 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006919 return;
6920 }
6921
6922 // Does the caller have this permission on the URI?
6923 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6924 // Right now, if you are not the original owner of the permission,
6925 // you are not allowed to revoke it.
6926 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6927 throw new SecurityException("Uid " + callingUid
6928 + " does not have permission to uri " + uri);
6929 //}
6930 }
6931
6932 // Go through all of the permissions and remove any that match.
6933 final List<String> SEGMENTS = uri.getPathSegments();
6934 if (SEGMENTS != null) {
6935 final int NS = SEGMENTS.size();
6936 int N = mGrantedUriPermissions.size();
6937 for (int i=0; i<N; i++) {
6938 HashMap<Uri, UriPermission> perms
6939 = mGrantedUriPermissions.valueAt(i);
6940 Iterator<UriPermission> it = perms.values().iterator();
6941 toploop:
6942 while (it.hasNext()) {
6943 UriPermission perm = it.next();
6944 Uri targetUri = perm.uri;
6945 if (!authority.equals(targetUri.getAuthority())) {
6946 continue;
6947 }
6948 List<String> targetSegments = targetUri.getPathSegments();
6949 if (targetSegments == null) {
6950 continue;
6951 }
6952 if (targetSegments.size() < NS) {
6953 continue;
6954 }
6955 for (int j=0; j<NS; j++) {
6956 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6957 continue toploop;
6958 }
6959 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006960 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006961 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006962 perm.clearModes(modeFlags);
6963 if (perm.modeFlags == 0) {
6964 it.remove();
6965 }
6966 }
6967 if (perms.size() == 0) {
6968 mGrantedUriPermissions.remove(
6969 mGrantedUriPermissions.keyAt(i));
6970 N--;
6971 i--;
6972 }
6973 }
6974 }
6975 }
6976
6977 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6978 int modeFlags) {
6979 synchronized(this) {
6980 final ProcessRecord r = getRecordForAppLocked(caller);
6981 if (r == null) {
6982 throw new SecurityException("Unable to find app for caller "
6983 + caller
6984 + " when revoking permission to uri " + uri);
6985 }
6986 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006987 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006988 return;
6989 }
6990
6991 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6992 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6993 if (modeFlags == 0) {
6994 return;
6995 }
6996
6997 final IPackageManager pm = ActivityThread.getPackageManager();
6998
6999 final String authority = uri.getAuthority();
7000 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07007001 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007002 if (cpr != null) {
7003 pi = cpr.info;
7004 } else {
7005 try {
7006 pi = pm.resolveContentProvider(authority,
7007 PackageManager.GET_URI_PERMISSION_PATTERNS);
7008 } catch (RemoteException ex) {
7009 }
7010 }
7011 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007012 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007013 return;
7014 }
7015
7016 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
7017 }
7018 }
7019
7020 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
7021 synchronized (this) {
7022 ProcessRecord app =
7023 who != null ? getRecordForAppLocked(who) : null;
7024 if (app == null) return;
7025
7026 Message msg = Message.obtain();
7027 msg.what = WAIT_FOR_DEBUGGER_MSG;
7028 msg.obj = app;
7029 msg.arg1 = waiting ? 1 : 0;
7030 mHandler.sendMessage(msg);
7031 }
7032 }
7033
7034 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
7035 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08007036 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007037 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08007038 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007039 }
7040
7041 // =========================================================
7042 // TASK MANAGEMENT
7043 // =========================================================
7044
7045 public List getTasks(int maxNum, int flags,
7046 IThumbnailReceiver receiver) {
7047 ArrayList list = new ArrayList();
7048
7049 PendingThumbnailsRecord pending = null;
7050 IApplicationThread topThumbnail = null;
7051 HistoryRecord topRecord = null;
7052
7053 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007054 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007055 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
7056 + ", receiver=" + receiver);
7057
7058 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
7059 != PackageManager.PERMISSION_GRANTED) {
7060 if (receiver != null) {
7061 // If the caller wants to wait for pending thumbnails,
7062 // it ain't gonna get them.
7063 try {
7064 receiver.finished();
7065 } catch (RemoteException ex) {
7066 }
7067 }
7068 String msg = "Permission Denial: getTasks() from pid="
7069 + Binder.getCallingPid()
7070 + ", uid=" + Binder.getCallingUid()
7071 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007072 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007073 throw new SecurityException(msg);
7074 }
7075
7076 int pos = mHistory.size()-1;
7077 HistoryRecord next =
7078 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
7079 HistoryRecord top = null;
7080 CharSequence topDescription = null;
7081 TaskRecord curTask = null;
7082 int numActivities = 0;
7083 int numRunning = 0;
7084 while (pos >= 0 && maxNum > 0) {
7085 final HistoryRecord r = next;
7086 pos--;
7087 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
7088
7089 // Initialize state for next task if needed.
7090 if (top == null ||
7091 (top.state == ActivityState.INITIALIZING
7092 && top.task == r.task)) {
7093 top = r;
7094 topDescription = r.description;
7095 curTask = r.task;
7096 numActivities = numRunning = 0;
7097 }
7098
7099 // Add 'r' into the current task.
7100 numActivities++;
7101 if (r.app != null && r.app.thread != null) {
7102 numRunning++;
7103 }
7104 if (topDescription == null) {
7105 topDescription = r.description;
7106 }
7107
Joe Onorato8a9b2202010-02-26 18:56:32 -08007108 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007109 TAG, r.intent.getComponent().flattenToShortString()
7110 + ": task=" + r.task);
7111
7112 // If the next one is a different task, generate a new
7113 // TaskInfo entry for what we have.
7114 if (next == null || next.task != curTask) {
7115 ActivityManager.RunningTaskInfo ci
7116 = new ActivityManager.RunningTaskInfo();
7117 ci.id = curTask.taskId;
7118 ci.baseActivity = r.intent.getComponent();
7119 ci.topActivity = top.intent.getComponent();
7120 ci.thumbnail = top.thumbnail;
7121 ci.description = topDescription;
7122 ci.numActivities = numActivities;
7123 ci.numRunning = numRunning;
7124 //System.out.println(
7125 // "#" + maxNum + ": " + " descr=" + ci.description);
7126 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007127 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007128 TAG, "State=" + top.state + "Idle=" + top.idle
7129 + " app=" + top.app
7130 + " thr=" + (top.app != null ? top.app.thread : null));
7131 if (top.state == ActivityState.RESUMED
7132 || top.state == ActivityState.PAUSING) {
7133 if (top.idle && top.app != null
7134 && top.app.thread != null) {
7135 topRecord = top;
7136 topThumbnail = top.app.thread;
7137 } else {
7138 top.thumbnailNeeded = true;
7139 }
7140 }
7141 if (pending == null) {
7142 pending = new PendingThumbnailsRecord(receiver);
7143 }
7144 pending.pendingRecords.add(top);
7145 }
7146 list.add(ci);
7147 maxNum--;
7148 top = null;
7149 }
7150 }
7151
7152 if (pending != null) {
7153 mPendingThumbnails.add(pending);
7154 }
7155 }
7156
Joe Onorato8a9b2202010-02-26 18:56:32 -08007157 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158
7159 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007160 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007161 try {
7162 topThumbnail.requestThumbnail(topRecord);
7163 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007164 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165 sendPendingThumbnail(null, topRecord, null, null, true);
7166 }
7167 }
7168
7169 if (pending == null && receiver != null) {
7170 // In this case all thumbnails were available and the client
7171 // is being asked to be told when the remaining ones come in...
7172 // which is unusually, since the top-most currently running
7173 // activity should never have a canned thumbnail! Oh well.
7174 try {
7175 receiver.finished();
7176 } catch (RemoteException ex) {
7177 }
7178 }
7179
7180 return list;
7181 }
7182
7183 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
7184 int flags) {
7185 synchronized (this) {
7186 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
7187 "getRecentTasks()");
7188
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007189 IPackageManager pm = ActivityThread.getPackageManager();
7190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007191 final int N = mRecentTasks.size();
7192 ArrayList<ActivityManager.RecentTaskInfo> res
7193 = new ArrayList<ActivityManager.RecentTaskInfo>(
7194 maxNum < N ? maxNum : N);
7195 for (int i=0; i<N && maxNum > 0; i++) {
7196 TaskRecord tr = mRecentTasks.get(i);
7197 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
7198 || (tr.intent == null)
7199 || ((tr.intent.getFlags()
7200 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
7201 ActivityManager.RecentTaskInfo rti
7202 = new ActivityManager.RecentTaskInfo();
7203 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
7204 rti.baseIntent = new Intent(
7205 tr.intent != null ? tr.intent : tr.affinityIntent);
7206 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007207
7208 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
7209 // Check whether this activity is currently available.
7210 try {
7211 if (rti.origActivity != null) {
7212 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
7213 continue;
7214 }
7215 } else if (rti.baseIntent != null) {
7216 if (pm.queryIntentActivities(rti.baseIntent,
7217 null, 0) == null) {
7218 continue;
7219 }
7220 }
7221 } catch (RemoteException e) {
7222 // Will never happen.
7223 }
7224 }
7225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007226 res.add(rti);
7227 maxNum--;
7228 }
7229 }
7230 return res;
7231 }
7232 }
7233
7234 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
7235 int j;
7236 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
7237 TaskRecord jt = startTask;
7238
7239 // First look backwards
7240 for (j=startIndex-1; j>=0; j--) {
7241 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7242 if (r.task != jt) {
7243 jt = r.task;
7244 if (affinity.equals(jt.affinity)) {
7245 return j;
7246 }
7247 }
7248 }
7249
7250 // Now look forwards
7251 final int N = mHistory.size();
7252 jt = startTask;
7253 for (j=startIndex+1; j<N; j++) {
7254 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7255 if (r.task != jt) {
7256 if (affinity.equals(jt.affinity)) {
7257 return j;
7258 }
7259 jt = r.task;
7260 }
7261 }
7262
7263 // Might it be at the top?
7264 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
7265 return N-1;
7266 }
7267
7268 return -1;
7269 }
7270
7271 /**
7272 * Perform a reset of the given task, if needed as part of launching it.
7273 * Returns the new HistoryRecord at the top of the task.
7274 */
7275 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
7276 HistoryRecord newActivity) {
7277 boolean forceReset = (newActivity.info.flags
7278 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
7279 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
7280 if ((newActivity.info.flags
7281 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
7282 forceReset = true;
7283 }
7284 }
7285
7286 final TaskRecord task = taskTop.task;
7287
7288 // We are going to move through the history list so that we can look
7289 // at each activity 'target' with 'below' either the interesting
7290 // activity immediately below it in the stack or null.
7291 HistoryRecord target = null;
7292 int targetI = 0;
7293 int taskTopI = -1;
7294 int replyChainEnd = -1;
7295 int lastReparentPos = -1;
7296 for (int i=mHistory.size()-1; i>=-1; i--) {
7297 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
7298
7299 if (below != null && below.finishing) {
7300 continue;
7301 }
7302 if (target == null) {
7303 target = below;
7304 targetI = i;
7305 // If we were in the middle of a reply chain before this
7306 // task, it doesn't appear like the root of the chain wants
7307 // anything interesting, so drop it.
7308 replyChainEnd = -1;
7309 continue;
7310 }
7311
7312 final int flags = target.info.flags;
7313
7314 final boolean finishOnTaskLaunch =
7315 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7316 final boolean allowTaskReparenting =
7317 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7318
7319 if (target.task == task) {
7320 // We are inside of the task being reset... we'll either
7321 // finish this activity, push it out for another task,
7322 // or leave it as-is. We only do this
7323 // for activities that are not the root of the task (since
7324 // if we finish the root, we may no longer have the task!).
7325 if (taskTopI < 0) {
7326 taskTopI = targetI;
7327 }
7328 if (below != null && below.task == task) {
7329 final boolean clearWhenTaskReset =
7330 (target.intent.getFlags()
7331 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007332 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007333 // If this activity is sending a reply to a previous
7334 // activity, we can't do anything with it now until
7335 // we reach the start of the reply chain.
7336 // XXX note that we are assuming the result is always
7337 // to the previous activity, which is almost always
7338 // the case but we really shouldn't count on.
7339 if (replyChainEnd < 0) {
7340 replyChainEnd = targetI;
7341 }
Ed Heyl73798232009-03-24 21:32:21 -07007342 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007343 && target.taskAffinity != null
7344 && !target.taskAffinity.equals(task.affinity)) {
7345 // If this activity has an affinity for another
7346 // task, then we need to move it out of here. We will
7347 // move it as far out of the way as possible, to the
7348 // bottom of the activity stack. This also keeps it
7349 // correctly ordered with any activities we previously
7350 // moved.
7351 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7352 if (target.taskAffinity != null
7353 && target.taskAffinity.equals(p.task.affinity)) {
7354 // If the activity currently at the bottom has the
7355 // same task affinity as the one we are moving,
7356 // then merge it into the same task.
7357 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007358 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007359 + " out to bottom task " + p.task);
7360 } else {
7361 mCurTask++;
7362 if (mCurTask <= 0) {
7363 mCurTask = 1;
7364 }
7365 target.task = new TaskRecord(mCurTask, target.info, null,
7366 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7367 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007368 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007369 + " out to new task " + target.task);
7370 }
7371 mWindowManager.setAppGroupId(target, task.taskId);
7372 if (replyChainEnd < 0) {
7373 replyChainEnd = targetI;
7374 }
7375 int dstPos = 0;
7376 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7377 p = (HistoryRecord)mHistory.get(srcPos);
7378 if (p.finishing) {
7379 continue;
7380 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007381 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007382 + " out to target's task " + target.task);
7383 task.numActivities--;
7384 p.task = target.task;
7385 target.task.numActivities++;
7386 mHistory.remove(srcPos);
7387 mHistory.add(dstPos, p);
7388 mWindowManager.moveAppToken(dstPos, p);
7389 mWindowManager.setAppGroupId(p, p.task.taskId);
7390 dstPos++;
7391 if (VALIDATE_TOKENS) {
7392 mWindowManager.validateAppTokens(mHistory);
7393 }
7394 i++;
7395 }
7396 if (taskTop == p) {
7397 taskTop = below;
7398 }
7399 if (taskTopI == replyChainEnd) {
7400 taskTopI = -1;
7401 }
7402 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007403 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007404 } else if (forceReset || finishOnTaskLaunch
7405 || clearWhenTaskReset) {
7406 // If the activity should just be removed -- either
7407 // because it asks for it, or the task should be
7408 // cleared -- then finish it and anything that is
7409 // part of its reply chain.
7410 if (clearWhenTaskReset) {
7411 // In this case, we want to finish this activity
7412 // and everything above it, so be sneaky and pretend
7413 // like these are all in the reply chain.
7414 replyChainEnd = targetI+1;
7415 while (replyChainEnd < mHistory.size() &&
7416 ((HistoryRecord)mHistory.get(
7417 replyChainEnd)).task == task) {
7418 replyChainEnd++;
7419 }
7420 replyChainEnd--;
7421 } else if (replyChainEnd < 0) {
7422 replyChainEnd = targetI;
7423 }
7424 HistoryRecord p = null;
7425 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7426 p = (HistoryRecord)mHistory.get(srcPos);
7427 if (p.finishing) {
7428 continue;
7429 }
7430 if (finishActivityLocked(p, srcPos,
7431 Activity.RESULT_CANCELED, null, "reset")) {
7432 replyChainEnd--;
7433 srcPos--;
7434 }
7435 }
7436 if (taskTop == p) {
7437 taskTop = below;
7438 }
7439 if (taskTopI == replyChainEnd) {
7440 taskTopI = -1;
7441 }
7442 replyChainEnd = -1;
7443 } else {
7444 // If we were in the middle of a chain, well the
7445 // activity that started it all doesn't want anything
7446 // special, so leave it all as-is.
7447 replyChainEnd = -1;
7448 }
7449 } else {
7450 // Reached the bottom of the task -- any reply chain
7451 // should be left as-is.
7452 replyChainEnd = -1;
7453 }
7454
7455 } else if (target.resultTo != null) {
7456 // If this activity is sending a reply to a previous
7457 // activity, we can't do anything with it now until
7458 // we reach the start of the reply chain.
7459 // XXX note that we are assuming the result is always
7460 // to the previous activity, which is almost always
7461 // the case but we really shouldn't count on.
7462 if (replyChainEnd < 0) {
7463 replyChainEnd = targetI;
7464 }
7465
7466 } else if (taskTopI >= 0 && allowTaskReparenting
7467 && task.affinity != null
7468 && task.affinity.equals(target.taskAffinity)) {
7469 // We are inside of another task... if this activity has
7470 // an affinity for our task, then either remove it if we are
7471 // clearing or move it over to our task. Note that
7472 // we currently punt on the case where we are resetting a
7473 // task that is not at the top but who has activities above
7474 // with an affinity to it... this is really not a normal
7475 // case, and we will need to later pull that task to the front
7476 // and usually at that point we will do the reset and pick
7477 // up those remaining activities. (This only happens if
7478 // someone starts an activity in a new task from an activity
7479 // in a task that is not currently on top.)
7480 if (forceReset || finishOnTaskLaunch) {
7481 if (replyChainEnd < 0) {
7482 replyChainEnd = targetI;
7483 }
7484 HistoryRecord p = null;
7485 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7486 p = (HistoryRecord)mHistory.get(srcPos);
7487 if (p.finishing) {
7488 continue;
7489 }
7490 if (finishActivityLocked(p, srcPos,
7491 Activity.RESULT_CANCELED, null, "reset")) {
7492 taskTopI--;
7493 lastReparentPos--;
7494 replyChainEnd--;
7495 srcPos--;
7496 }
7497 }
7498 replyChainEnd = -1;
7499 } else {
7500 if (replyChainEnd < 0) {
7501 replyChainEnd = targetI;
7502 }
7503 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7504 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7505 if (p.finishing) {
7506 continue;
7507 }
7508 if (lastReparentPos < 0) {
7509 lastReparentPos = taskTopI;
7510 taskTop = p;
7511 } else {
7512 lastReparentPos--;
7513 }
7514 mHistory.remove(srcPos);
7515 p.task.numActivities--;
7516 p.task = task;
7517 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007518 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007519 + " in to resetting task " + task);
7520 task.numActivities++;
7521 mWindowManager.moveAppToken(lastReparentPos, p);
7522 mWindowManager.setAppGroupId(p, p.task.taskId);
7523 if (VALIDATE_TOKENS) {
7524 mWindowManager.validateAppTokens(mHistory);
7525 }
7526 }
7527 replyChainEnd = -1;
7528
7529 // Now we've moved it in to place... but what if this is
7530 // a singleTop activity and we have put it on top of another
7531 // instance of the same activity? Then we drop the instance
7532 // below so it remains singleTop.
7533 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7534 for (int j=lastReparentPos-1; j>=0; j--) {
7535 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7536 if (p.finishing) {
7537 continue;
7538 }
7539 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7540 if (finishActivityLocked(p, j,
7541 Activity.RESULT_CANCELED, null, "replace")) {
7542 taskTopI--;
7543 lastReparentPos--;
7544 }
7545 }
7546 }
7547 }
7548 }
7549 }
7550
7551 target = below;
7552 targetI = i;
7553 }
7554
7555 return taskTop;
7556 }
7557
7558 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007559 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007560 */
7561 public void moveTaskToFront(int task) {
7562 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7563 "moveTaskToFront()");
7564
7565 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007566 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7567 Binder.getCallingUid(), "Task to front")) {
7568 return;
7569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 final long origId = Binder.clearCallingIdentity();
7571 try {
7572 int N = mRecentTasks.size();
7573 for (int i=0; i<N; i++) {
7574 TaskRecord tr = mRecentTasks.get(i);
7575 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007576 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007577 return;
7578 }
7579 }
7580 for (int i=mHistory.size()-1; i>=0; i--) {
7581 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7582 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007583 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007584 return;
7585 }
7586 }
7587 } finally {
7588 Binder.restoreCallingIdentity(origId);
7589 }
7590 }
7591 }
7592
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007593 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007594 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007595
7596 final int task = tr.taskId;
7597 int top = mHistory.size()-1;
7598
7599 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7600 // nothing to do!
7601 return;
7602 }
7603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007604 ArrayList moved = new ArrayList();
7605
7606 // Applying the affinities may have removed entries from the history,
7607 // so get the size again.
7608 top = mHistory.size()-1;
7609 int pos = top;
7610
7611 // Shift all activities with this task up to the top
7612 // of the stack, keeping them in the same internal order.
7613 while (pos >= 0) {
7614 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007615 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007616 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7617 boolean first = true;
7618 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007619 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007620 mHistory.remove(pos);
7621 mHistory.add(top, r);
7622 moved.add(0, r);
7623 top--;
7624 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007625 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007626 first = false;
7627 }
7628 }
7629 pos--;
7630 }
7631
Joe Onorato8a9b2202010-02-26 18:56:32 -08007632 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007633 "Prepare to front transition: task=" + tr);
7634 if (reason != null &&
7635 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7636 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7637 HistoryRecord r = topRunningActivityLocked(null);
7638 if (r != null) {
7639 mNoAnimActivities.add(r);
7640 }
7641 } else {
7642 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7643 }
7644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007645 mWindowManager.moveAppTokensToTop(moved);
7646 if (VALIDATE_TOKENS) {
7647 mWindowManager.validateAppTokens(mHistory);
7648 }
7649
Josh Bartel7f208742010-02-25 11:01:44 -06007650 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007651 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007652 }
7653
Josh Bartel7f208742010-02-25 11:01:44 -06007654 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007655 resumeTopActivityLocked(null);
7656 }
7657
7658 public void moveTaskToBack(int task) {
7659 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7660 "moveTaskToBack()");
7661
7662 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007663 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7664 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7665 Binder.getCallingUid(), "Task to back")) {
7666 return;
7667 }
7668 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007669 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007670 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007671 Binder.restoreCallingIdentity(origId);
7672 }
7673 }
7674
7675 /**
7676 * Moves an activity, and all of the other activities within the same task, to the bottom
7677 * of the history stack. The activity's order within the task is unchanged.
7678 *
7679 * @param token A reference to the activity we wish to move
7680 * @param nonRoot If false then this only works if the activity is the root
7681 * of a task; if true it will work for any activity in a task.
7682 * @return Returns true if the move completed, false if not.
7683 */
7684 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7685 synchronized(this) {
7686 final long origId = Binder.clearCallingIdentity();
7687 int taskId = getTaskForActivityLocked(token, !nonRoot);
7688 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007689 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690 }
7691 Binder.restoreCallingIdentity(origId);
7692 }
7693 return false;
7694 }
7695
7696 /**
7697 * Worker method for rearranging history stack. Implements the function of moving all
7698 * activities for a specific task (gathering them if disjoint) into a single group at the
7699 * bottom of the stack.
7700 *
7701 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7702 * to premeptively cancel the move.
7703 *
7704 * @param task The taskId to collect and move to the bottom.
7705 * @return Returns true if the move completed, false if not.
7706 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007707 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007708 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007709
7710 // If we have a watcher, preflight the move before committing to it. First check
7711 // for *other* available tasks, but if none are available, then try again allowing the
7712 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007713 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007714 HistoryRecord next = topRunningActivityLocked(null, task);
7715 if (next == null) {
7716 next = topRunningActivityLocked(null, 0);
7717 }
7718 if (next != null) {
7719 // ask watcher if this is allowed
7720 boolean moveOK = true;
7721 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007722 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007723 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007724 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007725 }
7726 if (!moveOK) {
7727 return false;
7728 }
7729 }
7730 }
7731
7732 ArrayList moved = new ArrayList();
7733
Joe Onorato8a9b2202010-02-26 18:56:32 -08007734 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007735 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007736
7737 final int N = mHistory.size();
7738 int bottom = 0;
7739 int pos = 0;
7740
7741 // Shift all activities with this task down to the bottom
7742 // of the stack, keeping them in the same internal order.
7743 while (pos < N) {
7744 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007745 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007746 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7747 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007748 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007749 mHistory.remove(pos);
7750 mHistory.add(bottom, r);
7751 moved.add(r);
7752 bottom++;
7753 }
7754 pos++;
7755 }
7756
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007757 if (reason != null &&
7758 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7759 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7760 HistoryRecord r = topRunningActivityLocked(null);
7761 if (r != null) {
7762 mNoAnimActivities.add(r);
7763 }
7764 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007765 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007766 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007767 mWindowManager.moveAppTokensToBottom(moved);
7768 if (VALIDATE_TOKENS) {
7769 mWindowManager.validateAppTokens(mHistory);
7770 }
7771
Josh Bartel7f208742010-02-25 11:01:44 -06007772 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007773 return true;
7774 }
7775
7776 public void moveTaskBackwards(int task) {
7777 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7778 "moveTaskBackwards()");
7779
7780 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007781 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7782 Binder.getCallingUid(), "Task backwards")) {
7783 return;
7784 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 final long origId = Binder.clearCallingIdentity();
7786 moveTaskBackwardsLocked(task);
7787 Binder.restoreCallingIdentity(origId);
7788 }
7789 }
7790
7791 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007792 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007793 }
7794
7795 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7796 synchronized(this) {
7797 return getTaskForActivityLocked(token, onlyRoot);
7798 }
7799 }
7800
7801 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7802 final int N = mHistory.size();
7803 TaskRecord lastTask = null;
7804 for (int i=0; i<N; i++) {
7805 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7806 if (r == token) {
7807 if (!onlyRoot || lastTask != r.task) {
7808 return r.task.taskId;
7809 }
7810 return -1;
7811 }
7812 lastTask = r.task;
7813 }
7814
7815 return -1;
7816 }
7817
7818 /**
7819 * Returns the top activity in any existing task matching the given
7820 * Intent. Returns null if no such task is found.
7821 */
7822 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7823 ComponentName cls = intent.getComponent();
7824 if (info.targetActivity != null) {
7825 cls = new ComponentName(info.packageName, info.targetActivity);
7826 }
7827
7828 TaskRecord cp = null;
7829
7830 final int N = mHistory.size();
7831 for (int i=(N-1); i>=0; i--) {
7832 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7833 if (!r.finishing && r.task != cp
7834 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7835 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007836 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007837 // + "/aff=" + r.task.affinity + " to new cls="
7838 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7839 if (r.task.affinity != null) {
7840 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007841 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007842 return r;
7843 }
7844 } else if (r.task.intent != null
7845 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007846 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007847 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007848 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007849 return r;
7850 } else if (r.task.affinityIntent != null
7851 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007852 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007853 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007854 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007855 return r;
7856 }
7857 }
7858 }
7859
7860 return null;
7861 }
7862
7863 /**
7864 * Returns the first activity (starting from the top of the stack) that
7865 * is the same as the given activity. Returns null if no such activity
7866 * is found.
7867 */
7868 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7869 ComponentName cls = intent.getComponent();
7870 if (info.targetActivity != null) {
7871 cls = new ComponentName(info.packageName, info.targetActivity);
7872 }
7873
7874 final int N = mHistory.size();
7875 for (int i=(N-1); i>=0; i--) {
7876 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7877 if (!r.finishing) {
7878 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007879 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007881 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 return r;
7883 }
7884 }
7885 }
7886
7887 return null;
7888 }
7889
7890 public void finishOtherInstances(IBinder token, ComponentName className) {
7891 synchronized(this) {
7892 final long origId = Binder.clearCallingIdentity();
7893
7894 int N = mHistory.size();
7895 TaskRecord lastTask = null;
7896 for (int i=0; i<N; i++) {
7897 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7898 if (r.realActivity.equals(className)
7899 && r != token && lastTask != r.task) {
7900 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7901 null, "others")) {
7902 i--;
7903 N--;
7904 }
7905 }
7906 lastTask = r.task;
7907 }
7908
7909 Binder.restoreCallingIdentity(origId);
7910 }
7911 }
7912
7913 // =========================================================
7914 // THUMBNAILS
7915 // =========================================================
7916
7917 public void reportThumbnail(IBinder token,
7918 Bitmap thumbnail, CharSequence description) {
7919 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7920 final long origId = Binder.clearCallingIdentity();
7921 sendPendingThumbnail(null, token, thumbnail, description, true);
7922 Binder.restoreCallingIdentity(origId);
7923 }
7924
7925 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7926 Bitmap thumbnail, CharSequence description, boolean always) {
7927 TaskRecord task = null;
7928 ArrayList receivers = null;
7929
7930 //System.out.println("Send pending thumbnail: " + r);
7931
7932 synchronized(this) {
7933 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007934 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935 if (index < 0) {
7936 return;
7937 }
7938 r = (HistoryRecord)mHistory.get(index);
7939 }
7940 if (thumbnail == null) {
7941 thumbnail = r.thumbnail;
7942 description = r.description;
7943 }
7944 if (thumbnail == null && !always) {
7945 // If there is no thumbnail, and this entry is not actually
7946 // going away, then abort for now and pick up the next
7947 // thumbnail we get.
7948 return;
7949 }
7950 task = r.task;
7951
7952 int N = mPendingThumbnails.size();
7953 int i=0;
7954 while (i<N) {
7955 PendingThumbnailsRecord pr =
7956 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7957 //System.out.println("Looking in " + pr.pendingRecords);
7958 if (pr.pendingRecords.remove(r)) {
7959 if (receivers == null) {
7960 receivers = new ArrayList();
7961 }
7962 receivers.add(pr);
7963 if (pr.pendingRecords.size() == 0) {
7964 pr.finished = true;
7965 mPendingThumbnails.remove(i);
7966 N--;
7967 continue;
7968 }
7969 }
7970 i++;
7971 }
7972 }
7973
7974 if (receivers != null) {
7975 final int N = receivers.size();
7976 for (int i=0; i<N; i++) {
7977 try {
7978 PendingThumbnailsRecord pr =
7979 (PendingThumbnailsRecord)receivers.get(i);
7980 pr.receiver.newThumbnail(
7981 task != null ? task.taskId : -1, thumbnail, description);
7982 if (pr.finished) {
7983 pr.receiver.finished();
7984 }
7985 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007986 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007987 }
7988 }
7989 }
7990 }
7991
7992 // =========================================================
7993 // CONTENT PROVIDERS
7994 // =========================================================
7995
7996 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7997 List providers = null;
7998 try {
7999 providers = ActivityThread.getPackageManager().
8000 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008001 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008002 } catch (RemoteException ex) {
8003 }
8004 if (providers != null) {
8005 final int N = providers.size();
8006 for (int i=0; i<N; i++) {
8007 ProviderInfo cpi =
8008 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008009 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008010 if (cpr == null) {
8011 cpr = new ContentProviderRecord(cpi, app.info);
8012 mProvidersByClass.put(cpi.name, cpr);
8013 }
8014 app.pubProviders.put(cpi.name, cpr);
8015 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008016 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008017 }
8018 }
8019 return providers;
8020 }
8021
8022 private final String checkContentProviderPermissionLocked(
8023 ProviderInfo cpi, ProcessRecord r, int mode) {
8024 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
8025 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
8026 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
8027 cpi.exported ? -1 : cpi.applicationInfo.uid)
8028 == PackageManager.PERMISSION_GRANTED
8029 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8030 return null;
8031 }
8032 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
8033 cpi.exported ? -1 : cpi.applicationInfo.uid)
8034 == PackageManager.PERMISSION_GRANTED) {
8035 return null;
8036 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07008037
8038 PathPermission[] pps = cpi.pathPermissions;
8039 if (pps != null) {
8040 int i = pps.length;
8041 while (i > 0) {
8042 i--;
8043 PathPermission pp = pps[i];
8044 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
8045 cpi.exported ? -1 : cpi.applicationInfo.uid)
8046 == PackageManager.PERMISSION_GRANTED
8047 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8048 return null;
8049 }
8050 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
8051 cpi.exported ? -1 : cpi.applicationInfo.uid)
8052 == PackageManager.PERMISSION_GRANTED) {
8053 return null;
8054 }
8055 }
8056 }
8057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008058 String msg = "Permission Denial: opening provider " + cpi.name
8059 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
8060 + ", uid=" + callingUid + ") requires "
8061 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008062 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008063 return msg;
8064 }
8065
8066 private final ContentProviderHolder getContentProviderImpl(
8067 IApplicationThread caller, String name) {
8068 ContentProviderRecord cpr;
8069 ProviderInfo cpi = null;
8070
8071 synchronized(this) {
8072 ProcessRecord r = null;
8073 if (caller != null) {
8074 r = getRecordForAppLocked(caller);
8075 if (r == null) {
8076 throw new SecurityException(
8077 "Unable to find app for caller " + caller
8078 + " (pid=" + Binder.getCallingPid()
8079 + ") when getting content provider " + name);
8080 }
8081 }
8082
8083 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07008084 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008085 if (cpr != null) {
8086 cpi = cpr.info;
8087 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8088 return new ContentProviderHolder(cpi,
8089 cpi.readPermission != null
8090 ? cpi.readPermission : cpi.writePermission);
8091 }
8092
8093 if (r != null && cpr.canRunHere(r)) {
8094 // This provider has been published or is in the process
8095 // of being published... but it is also allowed to run
8096 // in the caller's process, so don't make a connection
8097 // and just let the caller instantiate its own instance.
8098 if (cpr.provider != null) {
8099 // don't give caller the provider object, it needs
8100 // to make its own.
8101 cpr = new ContentProviderRecord(cpr);
8102 }
8103 return cpr;
8104 }
8105
8106 final long origId = Binder.clearCallingIdentity();
8107
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008108 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008109 // return it right away.
8110 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008111 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008112 "Adding provider requested by "
8113 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008114 + cpr.info.processName);
8115 Integer cnt = r.conProviders.get(cpr);
8116 if (cnt == null) {
8117 r.conProviders.put(cpr, new Integer(1));
8118 } else {
8119 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008121 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008122 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
8123 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07008124 // make sure to count it as being accessed and thus
8125 // back up on the LRU list. This is good because
8126 // content providers are often expensive to start.
8127 updateLruProcessLocked(cpr.app, false, true);
8128 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07008129 } else {
8130 cpr.externals++;
8131 }
8132
8133 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008134 updateOomAdjLocked(cpr.app);
8135 }
8136
8137 Binder.restoreCallingIdentity(origId);
8138
8139 } else {
8140 try {
8141 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008142 resolveContentProvider(name,
8143 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008144 } catch (RemoteException ex) {
8145 }
8146 if (cpi == null) {
8147 return null;
8148 }
8149
8150 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8151 return new ContentProviderHolder(cpi,
8152 cpi.readPermission != null
8153 ? cpi.readPermission : cpi.writePermission);
8154 }
8155
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008156 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
8157 && !cpi.processName.equals("system")) {
8158 // If this content provider does not run in the system
8159 // process, and the system is not yet ready to run other
8160 // processes, then fail fast instead of hanging.
8161 throw new IllegalArgumentException(
8162 "Attempt to launch content provider before system ready");
8163 }
8164
Dianne Hackborn860755f2010-06-03 18:47:52 -07008165 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008166 final boolean firstClass = cpr == null;
8167 if (firstClass) {
8168 try {
8169 ApplicationInfo ai =
8170 ActivityThread.getPackageManager().
8171 getApplicationInfo(
8172 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008173 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008174 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008175 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008176 + cpi.name);
8177 return null;
8178 }
8179 cpr = new ContentProviderRecord(cpi, ai);
8180 } catch (RemoteException ex) {
8181 // pm is in same process, this will never happen.
8182 }
8183 }
8184
8185 if (r != null && cpr.canRunHere(r)) {
8186 // If this is a multiprocess provider, then just return its
8187 // info and allow the caller to instantiate it. Only do
8188 // this if the provider is the same user as the caller's
8189 // process, or can run as root (so can be in any process).
8190 return cpr;
8191 }
8192
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008193 if (DEBUG_PROVIDER) {
8194 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08008195 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008196 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008197 }
8198
8199 // This is single process, and our app is now connecting to it.
8200 // See if we are already in the process of launching this
8201 // provider.
8202 final int N = mLaunchingProviders.size();
8203 int i;
8204 for (i=0; i<N; i++) {
8205 if (mLaunchingProviders.get(i) == cpr) {
8206 break;
8207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008208 }
8209
8210 // If the provider is not already being launched, then get it
8211 // started.
8212 if (i >= N) {
8213 final long origId = Binder.clearCallingIdentity();
8214 ProcessRecord proc = startProcessLocked(cpi.processName,
8215 cpr.appInfo, false, 0, "content provider",
8216 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008217 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008218 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008219 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008220 + cpi.applicationInfo.packageName + "/"
8221 + cpi.applicationInfo.uid + " for provider "
8222 + name + ": process is bad");
8223 return null;
8224 }
8225 cpr.launchingApp = proc;
8226 mLaunchingProviders.add(cpr);
8227 Binder.restoreCallingIdentity(origId);
8228 }
8229
8230 // Make sure the provider is published (the same provider class
8231 // may be published under multiple names).
8232 if (firstClass) {
8233 mProvidersByClass.put(cpi.name, cpr);
8234 }
8235 mProvidersByName.put(name, cpr);
8236
8237 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008238 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008239 "Adding provider requested by "
8240 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008241 + cpr.info.processName);
8242 Integer cnt = r.conProviders.get(cpr);
8243 if (cnt == null) {
8244 r.conProviders.put(cpr, new Integer(1));
8245 } else {
8246 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8247 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008248 cpr.clients.add(r);
8249 } else {
8250 cpr.externals++;
8251 }
8252 }
8253 }
8254
8255 // Wait for the provider to be published...
8256 synchronized (cpr) {
8257 while (cpr.provider == null) {
8258 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008259 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 + cpi.applicationInfo.packageName + "/"
8261 + cpi.applicationInfo.uid + " for provider "
8262 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008263 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008264 cpi.applicationInfo.packageName,
8265 cpi.applicationInfo.uid, name);
8266 return null;
8267 }
8268 try {
8269 cpr.wait();
8270 } catch (InterruptedException ex) {
8271 }
8272 }
8273 }
8274 return cpr;
8275 }
8276
8277 public final ContentProviderHolder getContentProvider(
8278 IApplicationThread caller, String name) {
8279 if (caller == null) {
8280 String msg = "null IApplicationThread when getting content provider "
8281 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008282 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008283 throw new SecurityException(msg);
8284 }
8285
8286 return getContentProviderImpl(caller, name);
8287 }
8288
8289 private ContentProviderHolder getContentProviderExternal(String name) {
8290 return getContentProviderImpl(null, name);
8291 }
8292
8293 /**
8294 * Drop a content provider from a ProcessRecord's bookkeeping
8295 * @param cpr
8296 */
8297 public void removeContentProvider(IApplicationThread caller, String name) {
8298 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008299 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008300 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008301 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008302 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008303 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008304 return;
8305 }
8306 final ProcessRecord r = getRecordForAppLocked(caller);
8307 if (r == null) {
8308 throw new SecurityException(
8309 "Unable to find app for caller " + caller +
8310 " when removing content provider " + name);
8311 }
8312 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008313 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008314 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008315 + r.info.processName + " from process "
8316 + localCpr.appInfo.processName);
8317 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008318 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008319 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008320 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008321 return;
8322 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008323 Integer cnt = r.conProviders.get(localCpr);
8324 if (cnt == null || cnt.intValue() <= 1) {
8325 localCpr.clients.remove(r);
8326 r.conProviders.remove(localCpr);
8327 } else {
8328 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008330 }
8331 updateOomAdjLocked();
8332 }
8333 }
8334
8335 private void removeContentProviderExternal(String name) {
8336 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008337 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008338 if(cpr == null) {
8339 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008340 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008341 return;
8342 }
8343
8344 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008345 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346 localCpr.externals--;
8347 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008348 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008349 }
8350 updateOomAdjLocked();
8351 }
8352 }
8353
8354 public final void publishContentProviders(IApplicationThread caller,
8355 List<ContentProviderHolder> providers) {
8356 if (providers == null) {
8357 return;
8358 }
8359
8360 synchronized(this) {
8361 final ProcessRecord r = getRecordForAppLocked(caller);
8362 if (r == null) {
8363 throw new SecurityException(
8364 "Unable to find app for caller " + caller
8365 + " (pid=" + Binder.getCallingPid()
8366 + ") when publishing content providers");
8367 }
8368
8369 final long origId = Binder.clearCallingIdentity();
8370
8371 final int N = providers.size();
8372 for (int i=0; i<N; i++) {
8373 ContentProviderHolder src = providers.get(i);
8374 if (src == null || src.info == null || src.provider == null) {
8375 continue;
8376 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07008377 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008378 if (dst != null) {
8379 mProvidersByClass.put(dst.info.name, dst);
8380 String names[] = dst.info.authority.split(";");
8381 for (int j = 0; j < names.length; j++) {
8382 mProvidersByName.put(names[j], dst);
8383 }
8384
8385 int NL = mLaunchingProviders.size();
8386 int j;
8387 for (j=0; j<NL; j++) {
8388 if (mLaunchingProviders.get(j) == dst) {
8389 mLaunchingProviders.remove(j);
8390 j--;
8391 NL--;
8392 }
8393 }
8394 synchronized (dst) {
8395 dst.provider = src.provider;
8396 dst.app = r;
8397 dst.notifyAll();
8398 }
8399 updateOomAdjLocked(r);
8400 }
8401 }
8402
8403 Binder.restoreCallingIdentity(origId);
8404 }
8405 }
8406
8407 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008408 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008409 synchronized (mSelf) {
8410 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8411 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008412 if (providers != null) {
8413 for (int i=providers.size()-1; i>=0; i--) {
8414 ProviderInfo pi = (ProviderInfo)providers.get(i);
8415 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8416 Slog.w(TAG, "Not installing system proc provider " + pi.name
8417 + ": not system .apk");
8418 providers.remove(i);
8419 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008420 }
8421 }
8422 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008423 if (providers != null) {
8424 mSystemThread.installSystemProviders(providers);
8425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008426 }
8427
8428 // =========================================================
8429 // GLOBAL MANAGEMENT
8430 // =========================================================
8431
8432 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8433 ApplicationInfo info, String customProcess) {
8434 String proc = customProcess != null ? customProcess : info.processName;
8435 BatteryStatsImpl.Uid.Proc ps = null;
8436 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8437 synchronized (stats) {
8438 ps = stats.getProcessStatsLocked(info.uid, proc);
8439 }
8440 return new ProcessRecord(ps, thread, info, proc);
8441 }
8442
8443 final ProcessRecord addAppLocked(ApplicationInfo info) {
8444 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8445
8446 if (app == null) {
8447 app = newProcessRecordLocked(null, info, null);
8448 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008449 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008450 }
8451
8452 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8453 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8454 app.persistent = true;
8455 app.maxAdj = CORE_SERVER_ADJ;
8456 }
8457 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8458 mPersistentStartingProcesses.add(app);
8459 startProcessLocked(app, "added application", app.processName);
8460 }
8461
8462 return app;
8463 }
8464
8465 public void unhandledBack() {
8466 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8467 "unhandledBack()");
8468
8469 synchronized(this) {
8470 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008471 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008472 TAG, "Performing unhandledBack(): stack size = " + count);
8473 if (count > 1) {
8474 final long origId = Binder.clearCallingIdentity();
8475 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8476 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8477 Binder.restoreCallingIdentity(origId);
8478 }
8479 }
8480 }
8481
8482 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8483 String name = uri.getAuthority();
8484 ContentProviderHolder cph = getContentProviderExternal(name);
8485 ParcelFileDescriptor pfd = null;
8486 if (cph != null) {
8487 // We record the binder invoker's uid in thread-local storage before
8488 // going to the content provider to open the file. Later, in the code
8489 // that handles all permissions checks, we look for this uid and use
8490 // that rather than the Activity Manager's own uid. The effect is that
8491 // we do the check against the caller's permissions even though it looks
8492 // to the content provider like the Activity Manager itself is making
8493 // the request.
8494 sCallerIdentity.set(new Identity(
8495 Binder.getCallingPid(), Binder.getCallingUid()));
8496 try {
8497 pfd = cph.provider.openFile(uri, "r");
8498 } catch (FileNotFoundException e) {
8499 // do nothing; pfd will be returned null
8500 } finally {
8501 // Ensure that whatever happens, we clean up the identity state
8502 sCallerIdentity.remove();
8503 }
8504
8505 // We've got the fd now, so we're done with the provider.
8506 removeContentProviderExternal(name);
8507 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008508 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008509 }
8510 return pfd;
8511 }
8512
8513 public void goingToSleep() {
8514 synchronized(this) {
8515 mSleeping = true;
8516 mWindowManager.setEventDispatching(false);
8517
8518 if (mResumedActivity != null) {
8519 pauseIfSleepingLocked();
8520 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008521 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522 }
8523 }
8524 }
8525
Dianne Hackborn55280a92009-05-07 15:53:46 -07008526 public boolean shutdown(int timeout) {
8527 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8528 != PackageManager.PERMISSION_GRANTED) {
8529 throw new SecurityException("Requires permission "
8530 + android.Manifest.permission.SHUTDOWN);
8531 }
8532
8533 boolean timedout = false;
8534
8535 synchronized(this) {
8536 mShuttingDown = true;
8537 mWindowManager.setEventDispatching(false);
8538
8539 if (mResumedActivity != null) {
8540 pauseIfSleepingLocked();
8541 final long endTime = System.currentTimeMillis() + timeout;
8542 while (mResumedActivity != null || mPausingActivity != null) {
8543 long delay = endTime - System.currentTimeMillis();
8544 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008545 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008546 timedout = true;
8547 break;
8548 }
8549 try {
8550 this.wait();
8551 } catch (InterruptedException e) {
8552 }
8553 }
8554 }
8555 }
8556
8557 mUsageStatsService.shutdown();
8558 mBatteryStatsService.shutdown();
8559
8560 return timedout;
8561 }
8562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008563 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008564 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008565 if (!mGoingToSleep.isHeld()) {
8566 mGoingToSleep.acquire();
8567 if (mLaunchingActivity.isHeld()) {
8568 mLaunchingActivity.release();
8569 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8570 }
8571 }
8572
8573 // If we are not currently pausing an activity, get the current
8574 // one to pause. If we are pausing one, we will just let that stuff
8575 // run and release the wake lock when all done.
8576 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008577 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8578 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008579 startPausingLocked(false, true);
8580 }
8581 }
8582 }
8583
8584 public void wakingUp() {
8585 synchronized(this) {
8586 if (mGoingToSleep.isHeld()) {
8587 mGoingToSleep.release();
8588 }
8589 mWindowManager.setEventDispatching(true);
8590 mSleeping = false;
8591 resumeTopActivityLocked(null);
8592 }
8593 }
8594
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008595 public void stopAppSwitches() {
8596 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8597 != PackageManager.PERMISSION_GRANTED) {
8598 throw new SecurityException("Requires permission "
8599 + android.Manifest.permission.STOP_APP_SWITCHES);
8600 }
8601
8602 synchronized(this) {
8603 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8604 + APP_SWITCH_DELAY_TIME;
8605 mDidAppSwitch = false;
8606 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8607 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8608 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8609 }
8610 }
8611
8612 public void resumeAppSwitches() {
8613 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8614 != PackageManager.PERMISSION_GRANTED) {
8615 throw new SecurityException("Requires permission "
8616 + android.Manifest.permission.STOP_APP_SWITCHES);
8617 }
8618
8619 synchronized(this) {
8620 // Note that we don't execute any pending app switches... we will
8621 // let those wait until either the timeout, or the next start
8622 // activity request.
8623 mAppSwitchesAllowedTime = 0;
8624 }
8625 }
8626
8627 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8628 String name) {
8629 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8630 return true;
8631 }
8632
8633 final int perm = checkComponentPermission(
8634 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8635 callingUid, -1);
8636 if (perm == PackageManager.PERMISSION_GRANTED) {
8637 return true;
8638 }
8639
Joe Onorato8a9b2202010-02-26 18:56:32 -08008640 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008641 return false;
8642 }
8643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 public void setDebugApp(String packageName, boolean waitForDebugger,
8645 boolean persistent) {
8646 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8647 "setDebugApp()");
8648
8649 // Note that this is not really thread safe if there are multiple
8650 // callers into it at the same time, but that's not a situation we
8651 // care about.
8652 if (persistent) {
8653 final ContentResolver resolver = mContext.getContentResolver();
8654 Settings.System.putString(
8655 resolver, Settings.System.DEBUG_APP,
8656 packageName);
8657 Settings.System.putInt(
8658 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8659 waitForDebugger ? 1 : 0);
8660 }
8661
8662 synchronized (this) {
8663 if (!persistent) {
8664 mOrigDebugApp = mDebugApp;
8665 mOrigWaitForDebugger = mWaitForDebugger;
8666 }
8667 mDebugApp = packageName;
8668 mWaitForDebugger = waitForDebugger;
8669 mDebugTransient = !persistent;
8670 if (packageName != null) {
8671 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008672 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008673 Binder.restoreCallingIdentity(origId);
8674 }
8675 }
8676 }
8677
8678 public void setAlwaysFinish(boolean enabled) {
8679 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8680 "setAlwaysFinish()");
8681
8682 Settings.System.putInt(
8683 mContext.getContentResolver(),
8684 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8685
8686 synchronized (this) {
8687 mAlwaysFinishActivities = enabled;
8688 }
8689 }
8690
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008691 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008692 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008693 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008694 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008695 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008696 }
8697 }
8698
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008699 public boolean isUserAMonkey() {
8700 // For now the fact that there is a controller implies
8701 // we have a monkey.
8702 synchronized (this) {
8703 return mController != null;
8704 }
8705 }
8706
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008707 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008708 synchronized (this) {
8709 mWatchers.register(watcher);
8710 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008711 }
8712
8713 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008714 synchronized (this) {
8715 mWatchers.unregister(watcher);
8716 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008717 }
8718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008719 public final void enterSafeMode() {
8720 synchronized(this) {
8721 // It only makes sense to do this before the system is ready
8722 // and started launching other packages.
8723 if (!mSystemReady) {
8724 try {
8725 ActivityThread.getPackageManager().enterSafeMode();
8726 } catch (RemoteException e) {
8727 }
8728
8729 View v = LayoutInflater.from(mContext).inflate(
8730 com.android.internal.R.layout.safe_mode, null);
8731 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8732 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8733 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8734 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8735 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8736 lp.format = v.getBackground().getOpacity();
8737 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8738 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8739 ((WindowManager)mContext.getSystemService(
8740 Context.WINDOW_SERVICE)).addView(v, lp);
8741 }
8742 }
8743 }
8744
8745 public void noteWakeupAlarm(IIntentSender sender) {
8746 if (!(sender instanceof PendingIntentRecord)) {
8747 return;
8748 }
8749 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8750 synchronized (stats) {
8751 if (mBatteryStatsService.isOnBattery()) {
8752 mBatteryStatsService.enforceCallingPermission();
8753 PendingIntentRecord rec = (PendingIntentRecord)sender;
8754 int MY_UID = Binder.getCallingUid();
8755 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8756 BatteryStatsImpl.Uid.Pkg pkg =
8757 stats.getPackageStatsLocked(uid, rec.key.packageName);
8758 pkg.incWakeupsLocked();
8759 }
8760 }
8761 }
8762
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008763 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008764 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008765 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008766 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008767 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008768 // XXX Note: don't acquire main activity lock here, because the window
8769 // manager calls in with its locks held.
8770
8771 boolean killed = false;
8772 synchronized (mPidsSelfLocked) {
8773 int[] types = new int[pids.length];
8774 int worstType = 0;
8775 for (int i=0; i<pids.length; i++) {
8776 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8777 if (proc != null) {
8778 int type = proc.setAdj;
8779 types[i] = type;
8780 if (type > worstType) {
8781 worstType = type;
8782 }
8783 }
8784 }
8785
8786 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8787 // then constrain it so we will kill all hidden procs.
8788 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8789 worstType = HIDDEN_APP_MIN_ADJ;
8790 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008791 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008792 for (int i=0; i<pids.length; i++) {
8793 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8794 if (proc == null) {
8795 continue;
8796 }
8797 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008798 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008799 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008800 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8801 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008802 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008803 proc.killedBackground = true;
8804 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008805 }
8806 }
8807 }
8808 return killed;
8809 }
8810
8811 public void reportPss(IApplicationThread caller, int pss) {
8812 Watchdog.PssRequestor req;
8813 String name;
8814 ProcessRecord callerApp;
8815 synchronized (this) {
8816 if (caller == null) {
8817 return;
8818 }
8819 callerApp = getRecordForAppLocked(caller);
8820 if (callerApp == null) {
8821 return;
8822 }
8823 callerApp.lastPss = pss;
8824 req = callerApp;
8825 name = callerApp.processName;
8826 }
8827 Watchdog.getInstance().reportPss(req, name, pss);
8828 if (!callerApp.persistent) {
8829 removeRequestedPss(callerApp);
8830 }
8831 }
8832
8833 public void requestPss(Runnable completeCallback) {
8834 ArrayList<ProcessRecord> procs;
8835 synchronized (this) {
8836 mRequestPssCallback = completeCallback;
8837 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008838 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8839 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008840 if (!proc.persistent) {
8841 mRequestPssList.add(proc);
8842 }
8843 }
8844 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8845 }
8846
8847 int oldPri = Process.getThreadPriority(Process.myTid());
8848 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8849 for (int i=procs.size()-1; i>=0; i--) {
8850 ProcessRecord proc = procs.get(i);
8851 proc.lastPss = 0;
8852 proc.requestPss();
8853 }
8854 Process.setThreadPriority(oldPri);
8855 }
8856
8857 void removeRequestedPss(ProcessRecord proc) {
8858 Runnable callback = null;
8859 synchronized (this) {
8860 if (mRequestPssList.remove(proc)) {
8861 if (mRequestPssList.size() == 0) {
8862 callback = mRequestPssCallback;
8863 mRequestPssCallback = null;
8864 }
8865 }
8866 }
8867
8868 if (callback != null) {
8869 callback.run();
8870 }
8871 }
8872
8873 public void collectPss(Watchdog.PssStats stats) {
8874 stats.mEmptyPss = 0;
8875 stats.mEmptyCount = 0;
8876 stats.mBackgroundPss = 0;
8877 stats.mBackgroundCount = 0;
8878 stats.mServicePss = 0;
8879 stats.mServiceCount = 0;
8880 stats.mVisiblePss = 0;
8881 stats.mVisibleCount = 0;
8882 stats.mForegroundPss = 0;
8883 stats.mForegroundCount = 0;
8884 stats.mNoPssCount = 0;
8885 synchronized (this) {
8886 int i;
8887 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8888 ? mProcDeaths.length : stats.mProcDeaths.length;
8889 int aggr = 0;
8890 for (i=0; i<NPD; i++) {
8891 aggr += mProcDeaths[i];
8892 stats.mProcDeaths[i] = aggr;
8893 }
8894 while (i<stats.mProcDeaths.length) {
8895 stats.mProcDeaths[i] = 0;
8896 i++;
8897 }
8898
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008899 for (i=mLruProcesses.size()-1; i>=0; i--) {
8900 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008901 if (proc.persistent) {
8902 continue;
8903 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008904 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008905 if (proc.lastPss == 0) {
8906 stats.mNoPssCount++;
8907 continue;
8908 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008909 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8910 if (proc.empty) {
8911 stats.mEmptyPss += proc.lastPss;
8912 stats.mEmptyCount++;
8913 } else {
8914 stats.mBackgroundPss += proc.lastPss;
8915 stats.mBackgroundCount++;
8916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008917 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8918 stats.mVisiblePss += proc.lastPss;
8919 stats.mVisibleCount++;
8920 } else {
8921 stats.mForegroundPss += proc.lastPss;
8922 stats.mForegroundCount++;
8923 }
8924 }
8925 }
8926 }
8927
8928 public final void startRunning(String pkg, String cls, String action,
8929 String data) {
8930 synchronized(this) {
8931 if (mStartRunning) {
8932 return;
8933 }
8934 mStartRunning = true;
8935 mTopComponent = pkg != null && cls != null
8936 ? new ComponentName(pkg, cls) : null;
8937 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8938 mTopData = data;
8939 if (!mSystemReady) {
8940 return;
8941 }
8942 }
8943
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008944 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008945 }
8946
8947 private void retrieveSettings() {
8948 final ContentResolver resolver = mContext.getContentResolver();
8949 String debugApp = Settings.System.getString(
8950 resolver, Settings.System.DEBUG_APP);
8951 boolean waitForDebugger = Settings.System.getInt(
8952 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8953 boolean alwaysFinishActivities = Settings.System.getInt(
8954 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8955
8956 Configuration configuration = new Configuration();
8957 Settings.System.getConfiguration(resolver, configuration);
8958
8959 synchronized (this) {
8960 mDebugApp = mOrigDebugApp = debugApp;
8961 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8962 mAlwaysFinishActivities = alwaysFinishActivities;
8963 // This happens before any activities are started, so we can
8964 // change mConfiguration in-place.
8965 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008966 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008967 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008968 }
8969 }
8970
8971 public boolean testIsSystemReady() {
8972 // no need to synchronize(this) just to read & return the value
8973 return mSystemReady;
8974 }
8975
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008976 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008977 // In the simulator, startRunning will never have been called, which
8978 // normally sets a few crucial variables. Do it here instead.
8979 if (!Process.supportsProcesses()) {
8980 mStartRunning = true;
8981 mTopAction = Intent.ACTION_MAIN;
8982 }
8983
8984 synchronized(this) {
8985 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008986 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008987 return;
8988 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008989
8990 // Check to see if there are any update receivers to run.
8991 if (!mDidUpdate) {
8992 if (mWaitingUpdate) {
8993 return;
8994 }
8995 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8996 List<ResolveInfo> ris = null;
8997 try {
8998 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8999 intent, null, 0);
9000 } catch (RemoteException e) {
9001 }
9002 if (ris != null) {
9003 for (int i=ris.size()-1; i>=0; i--) {
9004 if ((ris.get(i).activityInfo.applicationInfo.flags
9005 &ApplicationInfo.FLAG_SYSTEM) == 0) {
9006 ris.remove(i);
9007 }
9008 }
9009 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
9010 for (int i=0; i<ris.size(); i++) {
9011 ActivityInfo ai = ris.get(i).activityInfo;
9012 intent.setComponent(new ComponentName(ai.packageName, ai.name));
9013 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08009014 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009015 finisher = new IIntentReceiver.Stub() {
9016 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07009017 String data, Bundle extras, boolean ordered,
9018 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009019 throws RemoteException {
9020 synchronized (ActivityManagerService.this) {
9021 mDidUpdate = true;
9022 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009023 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009024 }
9025 };
9026 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009027 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009028 broadcastIntentLocked(null, null, intent, null, finisher,
9029 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08009030 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009031 mWaitingUpdate = true;
9032 }
9033 }
9034 }
9035 if (mWaitingUpdate) {
9036 return;
9037 }
9038 mDidUpdate = true;
9039 }
9040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 mSystemReady = true;
9042 if (!mStartRunning) {
9043 return;
9044 }
9045 }
9046
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009047 ArrayList<ProcessRecord> procsToKill = null;
9048 synchronized(mPidsSelfLocked) {
9049 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
9050 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
9051 if (!isAllowedWhileBooting(proc.info)){
9052 if (procsToKill == null) {
9053 procsToKill = new ArrayList<ProcessRecord>();
9054 }
9055 procsToKill.add(proc);
9056 }
9057 }
9058 }
9059
9060 if (procsToKill != null) {
9061 synchronized(this) {
9062 for (int i=procsToKill.size()-1; i>=0; i--) {
9063 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009064 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009065 removeProcessLocked(proc, true);
9066 }
9067 }
9068 }
9069
Joe Onorato8a9b2202010-02-26 18:56:32 -08009070 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009071 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009072 SystemClock.uptimeMillis());
9073
9074 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009075 // Make sure we have no pre-ready processes sitting around.
9076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
9078 ResolveInfo ri = mContext.getPackageManager()
9079 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07009080 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 CharSequence errorMsg = null;
9082 if (ri != null) {
9083 ActivityInfo ai = ri.activityInfo;
9084 ApplicationInfo app = ai.applicationInfo;
9085 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
9086 mTopAction = Intent.ACTION_FACTORY_TEST;
9087 mTopData = null;
9088 mTopComponent = new ComponentName(app.packageName,
9089 ai.name);
9090 } else {
9091 errorMsg = mContext.getResources().getText(
9092 com.android.internal.R.string.factorytest_not_system);
9093 }
9094 } else {
9095 errorMsg = mContext.getResources().getText(
9096 com.android.internal.R.string.factorytest_no_action);
9097 }
9098 if (errorMsg != null) {
9099 mTopAction = null;
9100 mTopData = null;
9101 mTopComponent = null;
9102 Message msg = Message.obtain();
9103 msg.what = SHOW_FACTORY_ERROR_MSG;
9104 msg.getData().putCharSequence("msg", errorMsg);
9105 mHandler.sendMessage(msg);
9106 }
9107 }
9108 }
9109
9110 retrieveSettings();
9111
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009112 if (goingCallback != null) goingCallback.run();
9113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009114 synchronized (this) {
9115 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
9116 try {
9117 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009118 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009119 if (apps != null) {
9120 int N = apps.size();
9121 int i;
9122 for (i=0; i<N; i++) {
9123 ApplicationInfo info
9124 = (ApplicationInfo)apps.get(i);
9125 if (info != null &&
9126 !info.packageName.equals("android")) {
9127 addAppLocked(info);
9128 }
9129 }
9130 }
9131 } catch (RemoteException ex) {
9132 // pm is in same process, this will never happen.
9133 }
9134 }
9135
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009136 // Start up initial activity.
9137 mBooting = true;
9138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009139 try {
9140 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
9141 Message msg = Message.obtain();
9142 msg.what = SHOW_UID_ERROR_MSG;
9143 mHandler.sendMessage(msg);
9144 }
9145 } catch (RemoteException e) {
9146 }
9147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009148 resumeTopActivityLocked(null);
9149 }
9150 }
9151
Dan Egnorb7f03672009-12-09 16:22:32 -08009152 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009153 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009154 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009155 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009156 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009157 startAppProblemLocked(app);
9158 app.stopFreezingAllLocked();
9159 return handleAppCrashLocked(app);
9160 }
9161
Dan Egnorb7f03672009-12-09 16:22:32 -08009162 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009163 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009164 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009165 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009166 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
9167 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009168 startAppProblemLocked(app);
9169 app.stopFreezingAllLocked();
9170 }
9171
9172 /**
9173 * Generate a process error record, suitable for attachment to a ProcessRecord.
9174 *
9175 * @param app The ProcessRecord in which the error occurred.
9176 * @param condition Crashing, Application Not Responding, etc. Values are defined in
9177 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08009178 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 * @param shortMsg Short message describing the crash.
9180 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08009181 * @param stackTrace Full crash stack trace, may be null.
9182 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 * @return Returns a fully-formed AppErrorStateInfo record.
9184 */
9185 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009186 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009187 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08009188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 report.condition = condition;
9190 report.processName = app.processName;
9191 report.pid = app.pid;
9192 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08009193 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009194 report.shortMsg = shortMsg;
9195 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08009196 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009197
9198 return report;
9199 }
9200
Dan Egnor42471dd2010-01-07 17:25:22 -08009201 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009202 synchronized (this) {
9203 app.crashing = false;
9204 app.crashingReport = null;
9205 app.notResponding = false;
9206 app.notRespondingReport = null;
9207 if (app.anrDialog == fromDialog) {
9208 app.anrDialog = null;
9209 }
9210 if (app.waitDialog == fromDialog) {
9211 app.waitDialog = null;
9212 }
9213 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009214 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07009215 Slog.i(ActivityManagerService.TAG, "Killing "
9216 + app.processName + " (pid=" + app.pid + "): user's request");
9217 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
9218 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009219 Process.killProcess(app.pid);
9220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 }
9222 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009223
Dan Egnorb7f03672009-12-09 16:22:32 -08009224 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009225 long now = SystemClock.uptimeMillis();
9226
9227 Long crashTime = mProcessCrashTimes.get(app.info.processName,
9228 app.info.uid);
9229 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
9230 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08009231 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009232 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009233 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009234 app.info.processName, app.info.uid);
9235 killServicesLocked(app, false);
9236 for (int i=mHistory.size()-1; i>=0; i--) {
9237 HistoryRecord r = (HistoryRecord)mHistory.get(i);
9238 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009239 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 + r.intent.getComponent().flattenToShortString());
9241 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
9242 }
9243 }
9244 if (!app.persistent) {
9245 // We don't want to start this process again until the user
9246 // explicitly does so... but for persistent process, we really
9247 // need to keep it running. If a persistent process is actually
9248 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08009249 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 app.info.processName);
9251 mBadProcesses.put(app.info.processName, app.info.uid, now);
9252 app.bad = true;
9253 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
9254 app.removed = true;
9255 removeProcessLocked(app, false);
9256 return false;
9257 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009258 } else {
9259 HistoryRecord r = topRunningActivityLocked(null);
9260 if (r.app == app) {
9261 // If the top running activity is from this crashing
9262 // process, then terminate it to avoid getting in a loop.
9263 Slog.w(TAG, " Force finishing activity "
9264 + r.intent.getComponent().flattenToShortString());
9265 int index = indexOfTokenLocked(r);
9266 finishActivityLocked(r, index,
9267 Activity.RESULT_CANCELED, null, "crashed");
9268 // Also terminate an activities below it that aren't yet
9269 // stopped, to avoid a situation where one will get
9270 // re-start our crashing activity once it gets resumed again.
9271 index--;
9272 if (index >= 0) {
9273 r = (HistoryRecord)mHistory.get(index);
9274 if (r.state == ActivityState.RESUMED
9275 || r.state == ActivityState.PAUSING
9276 || r.state == ActivityState.PAUSED) {
9277 if (!r.isHomeActivity) {
9278 Slog.w(TAG, " Force finishing activity "
9279 + r.intent.getComponent().flattenToShortString());
9280 finishActivityLocked(r, index,
9281 Activity.RESULT_CANCELED, null, "crashed");
9282 }
9283 }
9284 }
9285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009286 }
9287
9288 // Bump up the crash count of any services currently running in the proc.
9289 if (app.services.size() != 0) {
9290 // Any services running in the application need to be placed
9291 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009292 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009293 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009294 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 sr.crashCount++;
9296 }
9297 }
9298
9299 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
9300 return true;
9301 }
9302
9303 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009304 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9305 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009306 skipCurrentReceiverLocked(app);
9307 }
9308
9309 void skipCurrentReceiverLocked(ProcessRecord app) {
9310 boolean reschedule = false;
9311 BroadcastRecord r = app.curReceiver;
9312 if (r != null) {
9313 // The current broadcast is waiting for this app's receiver
9314 // to be finished. Looks like that's not going to happen, so
9315 // let the broadcast continue.
9316 logBroadcastReceiverDiscard(r);
9317 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9318 r.resultExtras, r.resultAbort, true);
9319 reschedule = true;
9320 }
9321 r = mPendingBroadcast;
9322 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009323 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009324 "skip & discard pending app " + r);
9325 logBroadcastReceiverDiscard(r);
9326 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9327 r.resultExtras, r.resultAbort, true);
9328 reschedule = true;
9329 }
9330 if (reschedule) {
9331 scheduleBroadcastsLocked();
9332 }
9333 }
9334
Dan Egnor60d87622009-12-16 16:32:58 -08009335 /**
9336 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9337 * The application process will exit immediately after this call returns.
9338 * @param app object of the crashing app, null for the system server
9339 * @param crashInfo describing the exception
9340 */
9341 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9342 ProcessRecord r = findAppProcess(app);
9343
9344 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9345 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009346 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009347 crashInfo.exceptionClassName,
9348 crashInfo.exceptionMessage,
9349 crashInfo.throwFileName,
9350 crashInfo.throwLineNumber);
9351
Dan Egnor42471dd2010-01-07 17:25:22 -08009352 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009353
9354 crashApplication(r, crashInfo);
9355 }
9356
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009357 public void handleApplicationStrictModeViolation(
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009358 IBinder app, int violationMask, ApplicationErrorReport.CrashInfo crashInfo) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009359 ProcessRecord r = findAppProcess(app);
9360 // TODO: implement
9361 Log.w(TAG, "handleApplicationStrictModeViolation.");
9362
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009363 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
9364 Integer crashFingerprint = crashInfo.stackTrace.hashCode();
9365 Log.d(TAG, "supposed to drop box for fingerprint " + crashFingerprint);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009366 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009367
9368 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
9369 AppErrorResult result = new AppErrorResult();
9370 synchronized (this) {
9371 final long origId = Binder.clearCallingIdentity();
9372
9373 Message msg = Message.obtain();
9374 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
9375 HashMap<String, Object> data = new HashMap<String, Object>();
9376 data.put("result", result);
9377 data.put("app", r);
9378 msg.obj = data;
9379 mHandler.sendMessage(msg);
9380
9381 Binder.restoreCallingIdentity(origId);
9382 }
9383 int res = result.get();
9384 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
9385 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009386 }
9387
Dan Egnor60d87622009-12-16 16:32:58 -08009388 /**
9389 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9390 * @param app object of the crashing app, null for the system server
9391 * @param tag reported by the caller
9392 * @param crashInfo describing the context of the error
9393 * @return true if the process should exit immediately (WTF is fatal)
9394 */
9395 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009396 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009397 ProcessRecord r = findAppProcess(app);
9398
9399 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9400 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009401 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009402 tag, crashInfo.exceptionMessage);
9403
Dan Egnor42471dd2010-01-07 17:25:22 -08009404 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009405
Doug Zongker43866e02010-01-07 12:09:54 -08009406 if (Settings.Secure.getInt(mContext.getContentResolver(),
9407 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009408 crashApplication(r, crashInfo);
9409 return true;
9410 } else {
9411 return false;
9412 }
9413 }
9414
9415 /**
9416 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9417 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9418 */
9419 private ProcessRecord findAppProcess(IBinder app) {
9420 if (app == null) {
9421 return null;
9422 }
9423
9424 synchronized (this) {
9425 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9426 final int NA = apps.size();
9427 for (int ia=0; ia<NA; ia++) {
9428 ProcessRecord p = apps.valueAt(ia);
9429 if (p.thread != null && p.thread.asBinder() == app) {
9430 return p;
9431 }
9432 }
9433 }
9434
Joe Onorato8a9b2202010-02-26 18:56:32 -08009435 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009436 return null;
9437 }
9438 }
9439
9440 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009441 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009442 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009443 * @param process which caused the error, null means the system server
9444 * @param activity which triggered the error, null if unknown
9445 * @param parent activity related to the error, null if unknown
9446 * @param subject line related to the error, null if absent
9447 * @param report in long form describing the error, null if absent
9448 * @param logFile to include in the report, null if none
9449 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009450 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009451 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009452 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9453 final String report, final File logFile,
9454 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009455 // NOTE -- this must never acquire the ActivityManagerService lock,
9456 // otherwise the watchdog may be prevented from resetting the system.
9457
Dan Egnora455d192010-03-12 08:52:28 -08009458 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009459 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009460 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009461 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009462 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009463 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009464 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009465 }
9466
Dan Egnora455d192010-03-12 08:52:28 -08009467 final String dropboxTag = prefix + eventType;
9468 final DropBoxManager dbox = (DropBoxManager)
9469 mContext.getSystemService(Context.DROPBOX_SERVICE);
9470
9471 // Exit early if the dropbox isn't configured to accept this report type.
9472 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9473
9474 final StringBuilder sb = new StringBuilder(1024);
9475 if (process == null || process.pid == MY_PID) {
9476 sb.append("Process: system_server\n");
9477 } else {
9478 sb.append("Process: ").append(process.processName).append("\n");
9479 }
9480 if (process != null) {
9481 int flags = process.info.flags;
9482 IPackageManager pm = ActivityThread.getPackageManager();
9483 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9484 for (String pkg : process.pkgList) {
9485 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009486 try {
Dan Egnora455d192010-03-12 08:52:28 -08009487 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9488 if (pi != null) {
9489 sb.append(" v").append(pi.versionCode);
9490 if (pi.versionName != null) {
9491 sb.append(" (").append(pi.versionName).append(")");
9492 }
9493 }
9494 } catch (RemoteException e) {
9495 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009496 }
Dan Egnora455d192010-03-12 08:52:28 -08009497 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009498 }
Dan Egnora455d192010-03-12 08:52:28 -08009499 }
9500 if (activity != null) {
9501 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9502 }
9503 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9504 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9505 }
9506 if (parent != null && parent != activity) {
9507 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9508 }
9509 if (subject != null) {
9510 sb.append("Subject: ").append(subject).append("\n");
9511 }
9512 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9513 sb.append("\n");
9514
9515 // Do the rest in a worker thread to avoid blocking the caller on I/O
9516 // (After this point, we shouldn't access AMS internal data structures.)
9517 Thread worker = new Thread("Error dump: " + dropboxTag) {
9518 @Override
9519 public void run() {
9520 if (report != null) {
9521 sb.append(report);
9522 }
9523 if (logFile != null) {
9524 try {
9525 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9526 } catch (IOException e) {
9527 Slog.e(TAG, "Error reading " + logFile, e);
9528 }
9529 }
9530 if (crashInfo != null && crashInfo.stackTrace != null) {
9531 sb.append(crashInfo.stackTrace);
9532 }
9533
9534 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9535 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9536 if (lines > 0) {
9537 sb.append("\n");
9538
9539 // Merge several logcat streams, and take the last N lines
9540 InputStreamReader input = null;
9541 try {
9542 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9543 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9544 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9545
9546 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9547 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9548 input = new InputStreamReader(logcat.getInputStream());
9549
9550 int num;
9551 char[] buf = new char[8192];
9552 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9553 } catch (IOException e) {
9554 Slog.e(TAG, "Error running logcat", e);
9555 } finally {
9556 if (input != null) try { input.close(); } catch (IOException e) {}
9557 }
9558 }
9559
9560 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009561 }
Dan Egnora455d192010-03-12 08:52:28 -08009562 };
9563
9564 if (process == null || process.pid == MY_PID) {
9565 worker.run(); // We may be about to die -- need to run this synchronously
9566 } else {
9567 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009568 }
9569 }
9570
9571 /**
9572 * Bring up the "unexpected error" dialog box for a crashing app.
9573 * Deal with edge cases (intercepts from instrumented applications,
9574 * ActivityController, error intent receivers, that sort of thing).
9575 * @param r the application crashing
9576 * @param crashInfo describing the failure
9577 */
9578 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009579 long timeMillis = System.currentTimeMillis();
9580 String shortMsg = crashInfo.exceptionClassName;
9581 String longMsg = crashInfo.exceptionMessage;
9582 String stackTrace = crashInfo.stackTrace;
9583 if (shortMsg != null && longMsg != null) {
9584 longMsg = shortMsg + ": " + longMsg;
9585 } else if (shortMsg != null) {
9586 longMsg = shortMsg;
9587 }
9588
Dan Egnor60d87622009-12-16 16:32:58 -08009589 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009590 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009591 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009592 try {
9593 String name = r != null ? r.processName : null;
9594 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009595 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009596 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009597 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598 + " at watcher's request");
9599 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009600 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009601 }
9602 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009603 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009604 }
9605 }
9606
9607 final long origId = Binder.clearCallingIdentity();
9608
9609 // If this process is running instrumentation, finish it.
9610 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009611 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009612 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009613 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9614 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009615 Bundle info = new Bundle();
9616 info.putString("shortMsg", shortMsg);
9617 info.putString("longMsg", longMsg);
9618 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9619 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009620 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009621 }
9622
Dan Egnor60d87622009-12-16 16:32:58 -08009623 // If we can't identify the process or it's already exceeded its crash quota,
9624 // quit right away without showing a crash dialog.
9625 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009627 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009628 }
9629
9630 Message msg = Message.obtain();
9631 msg.what = SHOW_ERROR_MSG;
9632 HashMap data = new HashMap();
9633 data.put("result", result);
9634 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009635 msg.obj = data;
9636 mHandler.sendMessage(msg);
9637
9638 Binder.restoreCallingIdentity(origId);
9639 }
9640
9641 int res = result.get();
9642
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009643 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009644 synchronized (this) {
9645 if (r != null) {
9646 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9647 SystemClock.uptimeMillis());
9648 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009649 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009650 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009651 }
9652 }
9653
9654 if (appErrorIntent != null) {
9655 try {
9656 mContext.startActivity(appErrorIntent);
9657 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009658 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009661 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009662
9663 Intent createAppErrorIntentLocked(ProcessRecord r,
9664 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9665 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009666 if (report == null) {
9667 return null;
9668 }
9669 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9670 result.setComponent(r.errorReportReceiver);
9671 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9672 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9673 return result;
9674 }
9675
Dan Egnorb7f03672009-12-09 16:22:32 -08009676 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9677 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009678 if (r.errorReportReceiver == null) {
9679 return null;
9680 }
9681
9682 if (!r.crashing && !r.notResponding) {
9683 return null;
9684 }
9685
Dan Egnorb7f03672009-12-09 16:22:32 -08009686 ApplicationErrorReport report = new ApplicationErrorReport();
9687 report.packageName = r.info.packageName;
9688 report.installerPackageName = r.errorReportReceiver.getPackageName();
9689 report.processName = r.processName;
9690 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009691 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009692
Dan Egnorb7f03672009-12-09 16:22:32 -08009693 if (r.crashing) {
9694 report.type = ApplicationErrorReport.TYPE_CRASH;
9695 report.crashInfo = crashInfo;
9696 } else if (r.notResponding) {
9697 report.type = ApplicationErrorReport.TYPE_ANR;
9698 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009699
Dan Egnorb7f03672009-12-09 16:22:32 -08009700 report.anrInfo.activity = r.notRespondingReport.tag;
9701 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9702 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009703 }
9704
Dan Egnorb7f03672009-12-09 16:22:32 -08009705 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009706 }
9707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009708 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9709 // assume our apps are happy - lazy create the list
9710 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9711
9712 synchronized (this) {
9713
9714 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009715 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9716 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009717 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9718 // This one's in trouble, so we'll generate a report for it
9719 // crashes are higher priority (in case there's a crash *and* an anr)
9720 ActivityManager.ProcessErrorStateInfo report = null;
9721 if (app.crashing) {
9722 report = app.crashingReport;
9723 } else if (app.notResponding) {
9724 report = app.notRespondingReport;
9725 }
9726
9727 if (report != null) {
9728 if (errList == null) {
9729 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9730 }
9731 errList.add(report);
9732 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009733 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009734 " crashing = " + app.crashing +
9735 " notResponding = " + app.notResponding);
9736 }
9737 }
9738 }
9739 }
9740
9741 return errList;
9742 }
9743
9744 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9745 // Lazy instantiation of list
9746 List<ActivityManager.RunningAppProcessInfo> runList = null;
9747 synchronized (this) {
9748 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009749 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9750 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009751 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9752 // Generate process state info for running application
9753 ActivityManager.RunningAppProcessInfo currApp =
9754 new ActivityManager.RunningAppProcessInfo(app.processName,
9755 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009756 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009758 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009759 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9760 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9761 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009762 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9763 } else if (adj >= HOME_APP_ADJ) {
9764 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9765 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009766 } else if (adj >= SECONDARY_SERVER_ADJ) {
9767 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07009768 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
9769 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
9770 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
9771 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009772 } else if (adj >= VISIBLE_APP_ADJ) {
9773 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9774 } else {
9775 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9776 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009777 currApp.importanceReasonCode = app.adjTypeCode;
9778 if (app.adjSource instanceof ProcessRecord) {
9779 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9780 } else if (app.adjSource instanceof HistoryRecord) {
9781 HistoryRecord r = (HistoryRecord)app.adjSource;
9782 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9783 }
9784 if (app.adjTarget instanceof ComponentName) {
9785 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9786 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009787 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788 // + " lru=" + currApp.lru);
9789 if (runList == null) {
9790 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9791 }
9792 runList.add(currApp);
9793 }
9794 }
9795 }
9796 return runList;
9797 }
9798
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009799 public List<ApplicationInfo> getRunningExternalApplications() {
9800 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9801 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9802 if (runningApps != null && runningApps.size() > 0) {
9803 Set<String> extList = new HashSet<String>();
9804 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9805 if (app.pkgList != null) {
9806 for (String pkg : app.pkgList) {
9807 extList.add(pkg);
9808 }
9809 }
9810 }
9811 IPackageManager pm = ActivityThread.getPackageManager();
9812 for (String pkg : extList) {
9813 try {
9814 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9815 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9816 retList.add(info);
9817 }
9818 } catch (RemoteException e) {
9819 }
9820 }
9821 }
9822 return retList;
9823 }
9824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009825 @Override
9826 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009827 if (checkCallingPermission(android.Manifest.permission.DUMP)
9828 != PackageManager.PERMISSION_GRANTED) {
9829 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9830 + Binder.getCallingPid()
9831 + ", uid=" + Binder.getCallingUid()
9832 + " without permission "
9833 + android.Manifest.permission.DUMP);
9834 return;
9835 }
9836
9837 boolean dumpAll = false;
9838
9839 int opti = 0;
9840 while (opti < args.length) {
9841 String opt = args[opti];
9842 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9843 break;
9844 }
9845 opti++;
9846 if ("-a".equals(opt)) {
9847 dumpAll = true;
9848 } else if ("-h".equals(opt)) {
9849 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009850 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009851 pw.println(" cmd may be one of:");
9852 pw.println(" activities: activity stack state");
9853 pw.println(" broadcasts: broadcast state");
9854 pw.println(" intents: pending intent state");
9855 pw.println(" processes: process state");
9856 pw.println(" providers: content provider state");
9857 pw.println(" services: service state");
9858 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009859 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009860 } else {
9861 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009862 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009863 }
9864
9865 // Is the caller requesting to dump a particular piece of data?
9866 if (opti < args.length) {
9867 String cmd = args[opti];
9868 opti++;
9869 if ("activities".equals(cmd) || "a".equals(cmd)) {
9870 synchronized (this) {
9871 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009872 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009873 return;
9874 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9875 synchronized (this) {
9876 dumpBroadcastsLocked(fd, pw, args, opti, true);
9877 }
9878 return;
9879 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9880 synchronized (this) {
9881 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9882 }
9883 return;
9884 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9885 synchronized (this) {
9886 dumpProcessesLocked(fd, pw, args, opti, true);
9887 }
9888 return;
9889 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9890 synchronized (this) {
9891 dumpProvidersLocked(fd, pw, args, opti, true);
9892 }
9893 return;
9894 } else if ("service".equals(cmd)) {
9895 dumpService(fd, pw, args, opti, true);
9896 return;
9897 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9898 synchronized (this) {
9899 dumpServicesLocked(fd, pw, args, opti, true);
9900 }
9901 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009902 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009903 }
9904
9905 // No piece of data specified, dump everything.
9906 synchronized (this) {
9907 boolean needSep;
9908 if (dumpAll) {
9909 pw.println("Providers in Current Activity Manager State:");
9910 }
9911 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9912 if (needSep) {
9913 pw.println(" ");
9914 }
9915 if (dumpAll) {
9916 pw.println("-------------------------------------------------------------------------------");
9917 pw.println("Broadcasts in Current Activity Manager State:");
9918 }
9919 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9920 if (needSep) {
9921 pw.println(" ");
9922 }
9923 if (dumpAll) {
9924 pw.println("-------------------------------------------------------------------------------");
9925 pw.println("Services in Current Activity Manager State:");
9926 }
9927 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9928 if (needSep) {
9929 pw.println(" ");
9930 }
9931 if (dumpAll) {
9932 pw.println("-------------------------------------------------------------------------------");
9933 pw.println("PendingIntents in Current Activity Manager State:");
9934 }
9935 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9936 if (needSep) {
9937 pw.println(" ");
9938 }
9939 if (dumpAll) {
9940 pw.println("-------------------------------------------------------------------------------");
9941 pw.println("Activities in Current Activity Manager State:");
9942 }
9943 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9944 if (needSep) {
9945 pw.println(" ");
9946 }
9947 if (dumpAll) {
9948 pw.println("-------------------------------------------------------------------------------");
9949 pw.println("Processes in Current Activity Manager State:");
9950 }
9951 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9952 }
9953 }
9954
9955 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9956 int opti, boolean dumpAll, boolean needHeader) {
9957 if (needHeader) {
9958 pw.println(" Activity stack:");
9959 }
9960 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9961 pw.println(" ");
9962 pw.println(" Running activities (most recent first):");
9963 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9964 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009965 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009966 pw.println(" Activities waiting for another to become visible:");
9967 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9968 }
9969 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009970 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009971 pw.println(" Activities waiting to stop:");
9972 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9973 }
9974 if (mFinishingActivities.size() > 0) {
9975 pw.println(" ");
9976 pw.println(" Activities waiting to finish:");
9977 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009979
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009980 pw.println(" ");
9981 pw.println(" mPausingActivity: " + mPausingActivity);
9982 pw.println(" mResumedActivity: " + mResumedActivity);
9983 pw.println(" mFocusedActivity: " + mFocusedActivity);
9984 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009985
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009986 if (dumpAll && mRecentTasks.size() > 0) {
9987 pw.println(" ");
9988 pw.println("Recent tasks in Current Activity Manager State:");
9989
9990 final int N = mRecentTasks.size();
9991 for (int i=0; i<N; i++) {
9992 TaskRecord tr = mRecentTasks.get(i);
9993 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9994 pw.println(tr);
9995 mRecentTasks.get(i).dump(pw, " ");
9996 }
9997 }
9998
9999 pw.println(" ");
10000 pw.println(" mCurTask: " + mCurTask);
10001
10002 return true;
10003 }
10004
10005 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10006 int opti, boolean dumpAll) {
10007 boolean needSep = false;
10008 int numPers = 0;
10009
10010 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010011 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
10012 final int NA = procs.size();
10013 for (int ia=0; ia<NA; ia++) {
10014 if (!needSep) {
10015 pw.println(" All known processes:");
10016 needSep = true;
10017 }
10018 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010019 pw.print(r.persistent ? " *PERS*" : " *APP*");
10020 pw.print(" UID "); pw.print(procs.keyAt(ia));
10021 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010022 r.dump(pw, " ");
10023 if (r.persistent) {
10024 numPers++;
10025 }
10026 }
10027 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010028 }
10029
10030 if (mLruProcesses.size() > 0) {
10031 if (needSep) pw.println(" ");
10032 needSep = true;
10033 pw.println(" Running processes (most recent first):");
10034 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010035 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010036 needSep = true;
10037 }
10038
10039 synchronized (mPidsSelfLocked) {
10040 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010041 if (needSep) pw.println(" ");
10042 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010043 pw.println(" PID mappings:");
10044 for (int i=0; i<mPidsSelfLocked.size(); i++) {
10045 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
10046 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010047 }
10048 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010049 }
10050
10051 if (mForegroundProcesses.size() > 0) {
10052 if (needSep) pw.println(" ");
10053 needSep = true;
10054 pw.println(" Foreground Processes:");
10055 for (int i=0; i<mForegroundProcesses.size(); i++) {
10056 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
10057 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010058 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010059 }
10060
10061 if (mPersistentStartingProcesses.size() > 0) {
10062 if (needSep) pw.println(" ");
10063 needSep = true;
10064 pw.println(" Persisent processes that are starting:");
10065 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
10066 "Starting Norm", "Restarting PERS", false);
10067 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010068
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010069 if (mStartingProcesses.size() > 0) {
10070 if (needSep) pw.println(" ");
10071 needSep = true;
10072 pw.println(" Processes that are starting:");
10073 dumpProcessList(pw, this, mStartingProcesses, " ",
10074 "Starting Norm", "Starting PERS", false);
10075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010076
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010077 if (mRemovedProcesses.size() > 0) {
10078 if (needSep) pw.println(" ");
10079 needSep = true;
10080 pw.println(" Processes that are being removed:");
10081 dumpProcessList(pw, this, mRemovedProcesses, " ",
10082 "Removed Norm", "Removed PERS", false);
10083 }
10084
10085 if (mProcessesOnHold.size() > 0) {
10086 if (needSep) pw.println(" ");
10087 needSep = true;
10088 pw.println(" Processes that are on old until the system is ready:");
10089 dumpProcessList(pw, this, mProcessesOnHold, " ",
10090 "OnHold Norm", "OnHold PERS", false);
10091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010092
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010093 if (mProcessesToGc.size() > 0) {
10094 if (needSep) pw.println(" ");
10095 needSep = true;
10096 pw.println(" Processes that are waiting to GC:");
10097 long now = SystemClock.uptimeMillis();
10098 for (int i=0; i<mProcessesToGc.size(); i++) {
10099 ProcessRecord proc = mProcessesToGc.get(i);
10100 pw.print(" Process "); pw.println(proc);
10101 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
10102 pw.print(", last gced=");
10103 pw.print(now-proc.lastRequestedGc);
10104 pw.print(" ms ago, last lowMem=");
10105 pw.print(now-proc.lastLowMemory);
10106 pw.println(" ms ago");
10107
10108 }
10109 }
10110
10111 if (mProcessCrashTimes.getMap().size() > 0) {
10112 if (needSep) pw.println(" ");
10113 needSep = true;
10114 pw.println(" Time since processes crashed:");
10115 long now = SystemClock.uptimeMillis();
10116 for (Map.Entry<String, SparseArray<Long>> procs
10117 : mProcessCrashTimes.getMap().entrySet()) {
10118 SparseArray<Long> uids = procs.getValue();
10119 final int N = uids.size();
10120 for (int i=0; i<N; i++) {
10121 pw.print(" Process "); pw.print(procs.getKey());
10122 pw.print(" uid "); pw.print(uids.keyAt(i));
10123 pw.print(": last crashed ");
10124 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010125 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010126 }
10127 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010129
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010130 if (mBadProcesses.getMap().size() > 0) {
10131 if (needSep) pw.println(" ");
10132 needSep = true;
10133 pw.println(" Bad processes:");
10134 for (Map.Entry<String, SparseArray<Long>> procs
10135 : mBadProcesses.getMap().entrySet()) {
10136 SparseArray<Long> uids = procs.getValue();
10137 final int N = uids.size();
10138 for (int i=0; i<N; i++) {
10139 pw.print(" Bad process "); pw.print(procs.getKey());
10140 pw.print(" uid "); pw.print(uids.keyAt(i));
10141 pw.print(": crashed at time ");
10142 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010143 }
10144 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010146
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010147 pw.println(" ");
10148 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010149 if (mHeavyWeightProcess != null) {
10150 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
10151 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010152 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -070010153 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010154 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
10155 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
10156 || mOrigWaitForDebugger) {
10157 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
10158 + " mDebugTransient=" + mDebugTransient
10159 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
10160 }
10161 if (mAlwaysFinishActivities || mController != null) {
10162 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
10163 + " mController=" + mController);
10164 }
10165 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010166 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010167 pw.println(" mStartRunning=" + mStartRunning
10168 + " mSystemReady=" + mSystemReady
10169 + " mBooting=" + mBooting
10170 + " mBooted=" + mBooted
10171 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010172 pw.println(" mGoingToSleep=" + mGoingToSleep);
10173 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -070010174 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010175 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010176
10177 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010178 }
10179
10180 /**
10181 * There are three ways to call this:
10182 * - no service specified: dump all the services
10183 * - a flattened component name that matched an existing service was specified as the
10184 * first arg: dump that one service
10185 * - the first arg isn't the flattened component name of an existing service:
10186 * dump all services whose component contains the first arg as a substring
10187 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010188 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
10189 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010190 String[] newArgs;
10191 String componentNameString;
10192 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -080010193 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010194 componentNameString = null;
10195 newArgs = EMPTY_STRING_ARRAY;
10196 r = null;
10197 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010198 componentNameString = args[opti];
10199 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010200 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
10201 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010202 newArgs = new String[args.length - opti];
10203 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010204 }
10205
10206 if (r != null) {
10207 dumpService(fd, pw, r, newArgs);
10208 } else {
10209 for (ServiceRecord r1 : mServices.values()) {
10210 if (componentNameString == null
10211 || r1.name.flattenToString().contains(componentNameString)) {
10212 dumpService(fd, pw, r1, newArgs);
10213 }
10214 }
10215 }
10216 }
10217
10218 /**
10219 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
10220 * there is a thread associated with the service.
10221 */
10222 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
10223 pw.println(" Service " + r.name.flattenToString());
10224 if (r.app != null && r.app.thread != null) {
10225 try {
10226 // flush anything that is already in the PrintWriter since the thread is going
10227 // to write to the file descriptor directly
10228 pw.flush();
10229 r.app.thread.dumpService(fd, r, args);
10230 pw.print("\n");
10231 } catch (RemoteException e) {
10232 pw.println("got a RemoteException while dumping the service");
10233 }
10234 }
10235 }
10236
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010237 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10238 int opti, boolean dumpAll) {
10239 boolean needSep = false;
10240
10241 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 if (mRegisteredReceivers.size() > 0) {
10243 pw.println(" ");
10244 pw.println(" Registered Receivers:");
10245 Iterator it = mRegisteredReceivers.values().iterator();
10246 while (it.hasNext()) {
10247 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010248 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249 r.dump(pw, " ");
10250 }
10251 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010253 pw.println(" ");
10254 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010255 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010256 needSep = true;
10257 }
10258
10259 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
10260 || mPendingBroadcast != null) {
10261 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010262 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010263 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010264 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010265 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10266 pw.println(" Broadcast #" + i + ":");
10267 mParallelBroadcasts.get(i).dump(pw, " ");
10268 }
10269 if (mOrderedBroadcasts.size() > 0) {
10270 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010271 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010272 }
10273 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10274 pw.println(" Serialized Broadcast #" + i + ":");
10275 mOrderedBroadcasts.get(i).dump(pw, " ");
10276 }
10277 pw.println(" ");
10278 pw.println(" Pending broadcast:");
10279 if (mPendingBroadcast != null) {
10280 mPendingBroadcast.dump(pw, " ");
10281 } else {
10282 pw.println(" (null)");
10283 }
10284 needSep = true;
10285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010286
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010287 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010288 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -080010289 pw.println(" Historical broadcasts:");
10290 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
10291 BroadcastRecord r = mBroadcastHistory[i];
10292 if (r == null) {
10293 break;
10294 }
10295 pw.println(" Historical Broadcast #" + i + ":");
10296 r.dump(pw, " ");
10297 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010298 needSep = true;
10299 }
10300
10301 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010302 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010303 pw.println(" Sticky broadcasts:");
10304 StringBuilder sb = new StringBuilder(128);
10305 for (Map.Entry<String, ArrayList<Intent>> ent
10306 : mStickyBroadcasts.entrySet()) {
10307 pw.print(" * Sticky action "); pw.print(ent.getKey());
10308 pw.println(":");
10309 ArrayList<Intent> intents = ent.getValue();
10310 final int N = intents.size();
10311 for (int i=0; i<N; i++) {
10312 sb.setLength(0);
10313 sb.append(" Intent: ");
10314 intents.get(i).toShortString(sb, true, false);
10315 pw.println(sb.toString());
10316 Bundle bundle = intents.get(i).getExtras();
10317 if (bundle != null) {
10318 pw.print(" ");
10319 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010320 }
10321 }
10322 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010323 needSep = true;
10324 }
10325
10326 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010328 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010329 pw.println(" mHandler:");
10330 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010331 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010332 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010333
10334 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010335 }
10336
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010337 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10338 int opti, boolean dumpAll) {
10339 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010340
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010341 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010342 if (mServices.size() > 0) {
10343 pw.println(" Active services:");
10344 Iterator<ServiceRecord> it = mServices.values().iterator();
10345 while (it.hasNext()) {
10346 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010347 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010348 r.dump(pw, " ");
10349 }
10350 needSep = true;
10351 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010353
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010354 if (mPendingServices.size() > 0) {
10355 if (needSep) pw.println(" ");
10356 pw.println(" Pending services:");
10357 for (int i=0; i<mPendingServices.size(); i++) {
10358 ServiceRecord r = mPendingServices.get(i);
10359 pw.print(" * Pending "); pw.println(r);
10360 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010361 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010362 needSep = true;
10363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010364
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010365 if (mRestartingServices.size() > 0) {
10366 if (needSep) pw.println(" ");
10367 pw.println(" Restarting services:");
10368 for (int i=0; i<mRestartingServices.size(); i++) {
10369 ServiceRecord r = mRestartingServices.get(i);
10370 pw.print(" * Restarting "); pw.println(r);
10371 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010372 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010373 needSep = true;
10374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010375
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010376 if (mStoppingServices.size() > 0) {
10377 if (needSep) pw.println(" ");
10378 pw.println(" Stopping services:");
10379 for (int i=0; i<mStoppingServices.size(); i++) {
10380 ServiceRecord r = mStoppingServices.get(i);
10381 pw.print(" * Stopping "); pw.println(r);
10382 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010383 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010384 needSep = true;
10385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010386
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010387 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010388 if (mServiceConnections.size() > 0) {
10389 if (needSep) pw.println(" ");
10390 pw.println(" Connection bindings to services:");
10391 Iterator<ConnectionRecord> it
10392 = mServiceConnections.values().iterator();
10393 while (it.hasNext()) {
10394 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010395 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010396 r.dump(pw, " ");
10397 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010398 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010399 }
10400 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010401
10402 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010403 }
10404
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010405 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10406 int opti, boolean dumpAll) {
10407 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010408
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010409 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010410 if (mProvidersByClass.size() > 0) {
10411 if (needSep) pw.println(" ");
10412 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010413 Iterator<Map.Entry<String, ContentProviderRecord>> it
10414 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010415 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010416 Map.Entry<String, ContentProviderRecord> e = it.next();
10417 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010418 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010419 r.dump(pw, " ");
10420 }
10421 needSep = true;
10422 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010423
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010424 if (mProvidersByName.size() > 0) {
10425 pw.println(" ");
10426 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010427 Iterator<Map.Entry<String, ContentProviderRecord>> it
10428 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010429 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010430 Map.Entry<String, ContentProviderRecord> e = it.next();
10431 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010432 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10433 pw.println(r);
10434 }
10435 needSep = true;
10436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010437 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010438
10439 if (mLaunchingProviders.size() > 0) {
10440 if (needSep) pw.println(" ");
10441 pw.println(" Launching content providers:");
10442 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10443 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10444 pw.println(mLaunchingProviders.get(i));
10445 }
10446 needSep = true;
10447 }
10448
10449 if (mGrantedUriPermissions.size() > 0) {
10450 pw.println();
10451 pw.println("Granted Uri Permissions:");
10452 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10453 int uid = mGrantedUriPermissions.keyAt(i);
10454 HashMap<Uri, UriPermission> perms
10455 = mGrantedUriPermissions.valueAt(i);
10456 pw.print(" * UID "); pw.print(uid);
10457 pw.println(" holds:");
10458 for (UriPermission perm : perms.values()) {
10459 pw.print(" "); pw.println(perm);
10460 perm.dump(pw, " ");
10461 }
10462 }
10463 needSep = true;
10464 }
10465
10466 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010467 }
10468
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010469 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10470 int opti, boolean dumpAll) {
10471 boolean needSep = false;
10472
10473 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010474 if (this.mIntentSenderRecords.size() > 0) {
10475 Iterator<WeakReference<PendingIntentRecord>> it
10476 = mIntentSenderRecords.values().iterator();
10477 while (it.hasNext()) {
10478 WeakReference<PendingIntentRecord> ref = it.next();
10479 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010480 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010481 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010482 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010483 rec.dump(pw, " ");
10484 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010485 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010486 }
10487 }
10488 }
10489 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010490
10491 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010492 }
10493
10494 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010495 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010496 TaskRecord lastTask = null;
10497 for (int i=list.size()-1; i>=0; i--) {
10498 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010499 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010500 if (lastTask != r.task) {
10501 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010502 pw.print(prefix);
10503 pw.print(full ? "* " : " ");
10504 pw.println(lastTask);
10505 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010506 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010508 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010509 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10510 pw.print(" #"); pw.print(i); pw.print(": ");
10511 pw.println(r);
10512 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010513 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010514 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010515 }
10516 }
10517
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010518 private static String buildOomTag(String prefix, String space, int val, int base) {
10519 if (val == base) {
10520 if (space == null) return prefix;
10521 return prefix + " ";
10522 }
10523 return prefix + "+" + Integer.toString(val-base);
10524 }
10525
10526 private static final int dumpProcessList(PrintWriter pw,
10527 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528 String prefix, String normalLabel, String persistentLabel,
10529 boolean inclOomAdj) {
10530 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010531 final int N = list.size()-1;
10532 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010533 ProcessRecord r = (ProcessRecord)list.get(i);
10534 if (false) {
10535 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10536 + " #" + i + ":");
10537 r.dump(pw, prefix + " ");
10538 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010539 String oomAdj;
10540 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010541 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010542 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010543 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10544 } else if (r.setAdj >= HOME_APP_ADJ) {
10545 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10546 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10547 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10548 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10549 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010550 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
10551 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
10552 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
10553 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010554 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10555 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10556 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10557 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010558 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010559 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010560 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010561 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010562 } else {
10563 oomAdj = Integer.toString(r.setAdj);
10564 }
10565 String schedGroup;
10566 switch (r.setSchedGroup) {
10567 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10568 schedGroup = "B";
10569 break;
10570 case Process.THREAD_GROUP_DEFAULT:
10571 schedGroup = "F";
10572 break;
10573 default:
10574 schedGroup = Integer.toString(r.setSchedGroup);
10575 break;
10576 }
10577 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010578 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010579 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010580 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010581 pw.print(prefix);
10582 pw.print(" ");
10583 if (r.adjTarget instanceof ComponentName) {
10584 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
10585 } else if (r.adjTarget != null) {
10586 pw.print(r.adjTarget.toString());
10587 } else {
10588 pw.print("{null}");
10589 }
10590 pw.print("<=");
10591 if (r.adjSource instanceof ProcessRecord) {
10592 pw.print("Proc{");
10593 pw.print(((ProcessRecord)r.adjSource).toShortString());
10594 pw.println("}");
10595 } else if (r.adjSource != null) {
10596 pw.println(r.adjSource.toString());
10597 } else {
10598 pw.println("{null}");
10599 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010600 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010601 } else {
10602 pw.println(String.format("%s%s #%2d: %s",
10603 prefix, (r.persistent ? persistentLabel : normalLabel),
10604 i, r.toString()));
10605 }
10606 if (r.persistent) {
10607 numPers++;
10608 }
10609 }
10610 return numPers;
10611 }
10612
Dianne Hackborn472ad872010-04-07 17:31:48 -070010613 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010615 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010616 long uptime = SystemClock.uptimeMillis();
10617 long realtime = SystemClock.elapsedRealtime();
10618
10619 if (isCheckinRequest) {
10620 // short checkin version
10621 pw.println(uptime + "," + realtime);
10622 pw.flush();
10623 } else {
10624 pw.println("Applications Memory Usage (kB):");
10625 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10626 }
10627 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10628 ProcessRecord r = (ProcessRecord)list.get(i);
10629 if (r.thread != null) {
10630 if (!isCheckinRequest) {
10631 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10632 pw.flush();
10633 }
10634 try {
10635 r.thread.asBinder().dump(fd, args);
10636 } catch (RemoteException e) {
10637 if (!isCheckinRequest) {
10638 pw.println("Got RemoteException!");
10639 pw.flush();
10640 }
10641 }
10642 }
10643 }
10644 }
10645
10646 /**
10647 * Searches array of arguments for the specified string
10648 * @param args array of argument strings
10649 * @param value value to search for
10650 * @return true if the value is contained in the array
10651 */
10652 private static boolean scanArgs(String[] args, String value) {
10653 if (args != null) {
10654 for (String arg : args) {
10655 if (value.equals(arg)) {
10656 return true;
10657 }
10658 }
10659 }
10660 return false;
10661 }
10662
Dianne Hackborn75b03852009-06-12 15:43:26 -070010663 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010664 int count = mHistory.size();
10665
10666 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667 int index = -1;
10668 for (int i=count-1; i>=0; i--) {
10669 Object o = mHistory.get(i);
10670 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010671 index = i;
10672 break;
10673 }
10674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010675
10676 return index;
10677 }
10678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010679 private final void killServicesLocked(ProcessRecord app,
10680 boolean allowRestart) {
10681 // Report disconnected services.
10682 if (false) {
10683 // XXX we are letting the client link to the service for
10684 // death notifications.
10685 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010686 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010687 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010688 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010689 if (r.connections.size() > 0) {
10690 Iterator<ConnectionRecord> jt
10691 = r.connections.values().iterator();
10692 while (jt.hasNext()) {
10693 ConnectionRecord c = jt.next();
10694 if (c.binding.client != app) {
10695 try {
10696 //c.conn.connected(r.className, null);
10697 } catch (Exception e) {
10698 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010699 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010700 + r.shortName
10701 + " from app " + app.processName, e);
10702 }
10703 }
10704 }
10705 }
10706 }
10707 }
10708 }
10709
10710 // Clean up any connections this application has to other services.
10711 if (app.connections.size() > 0) {
10712 Iterator<ConnectionRecord> it = app.connections.iterator();
10713 while (it.hasNext()) {
10714 ConnectionRecord r = it.next();
10715 removeConnectionLocked(r, app, null);
10716 }
10717 }
10718 app.connections.clear();
10719
10720 if (app.services.size() != 0) {
10721 // Any services running in the application need to be placed
10722 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010723 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010724 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010725 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010726 synchronized (sr.stats.getBatteryStats()) {
10727 sr.stats.stopLaunchedLocked();
10728 }
10729 sr.app = null;
10730 sr.executeNesting = 0;
10731 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010732
10733 boolean hasClients = sr.bindings.size() > 0;
10734 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010735 Iterator<IntentBindRecord> bindings
10736 = sr.bindings.values().iterator();
10737 while (bindings.hasNext()) {
10738 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010739 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010740 + ": shouldUnbind=" + b.hasBound);
10741 b.binder = null;
10742 b.requested = b.received = b.hasBound = false;
10743 }
10744 }
10745
10746 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010747 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010748 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010749 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010750 sr.crashCount, sr.shortName, app.pid);
10751 bringDownServiceLocked(sr, true);
10752 } else if (!allowRestart) {
10753 bringDownServiceLocked(sr, true);
10754 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010755 boolean canceled = scheduleServiceRestartLocked(sr, true);
10756
10757 // Should the service remain running? Note that in the
10758 // extreme case of so many attempts to deliver a command
10759 // that it failed, that we also will stop it here.
10760 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10761 if (sr.pendingStarts.size() == 0) {
10762 sr.startRequested = false;
10763 if (!hasClients) {
10764 // Whoops, no reason to restart!
10765 bringDownServiceLocked(sr, true);
10766 }
10767 }
10768 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010769 }
10770 }
10771
10772 if (!allowRestart) {
10773 app.services.clear();
10774 }
10775 }
10776
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010777 // Make sure we have no more records on the stopping list.
10778 int i = mStoppingServices.size();
10779 while (i > 0) {
10780 i--;
10781 ServiceRecord sr = mStoppingServices.get(i);
10782 if (sr.app == app) {
10783 mStoppingServices.remove(i);
10784 }
10785 }
10786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010787 app.executingServices.clear();
10788 }
10789
10790 private final void removeDyingProviderLocked(ProcessRecord proc,
10791 ContentProviderRecord cpr) {
10792 synchronized (cpr) {
10793 cpr.launchingApp = null;
10794 cpr.notifyAll();
10795 }
10796
10797 mProvidersByClass.remove(cpr.info.name);
10798 String names[] = cpr.info.authority.split(";");
10799 for (int j = 0; j < names.length; j++) {
10800 mProvidersByName.remove(names[j]);
10801 }
10802
10803 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10804 while (cit.hasNext()) {
10805 ProcessRecord capp = cit.next();
10806 if (!capp.persistent && capp.thread != null
10807 && capp.pid != 0
10808 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010809 Slog.i(TAG, "Kill " + capp.processName
10810 + " (pid " + capp.pid + "): provider " + cpr.info.name
10811 + " in dying process " + proc.processName);
10812 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10813 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010814 Process.killProcess(capp.pid);
10815 }
10816 }
10817
10818 mLaunchingProviders.remove(cpr);
10819 }
10820
10821 /**
10822 * Main code for cleaning up a process when it has gone away. This is
10823 * called both as a result of the process dying, or directly when stopping
10824 * a process when running in single process mode.
10825 */
10826 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10827 boolean restarting, int index) {
10828 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010829 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010830 }
10831
Dianne Hackborn36124872009-10-08 16:22:03 -070010832 mProcessesToGc.remove(app);
10833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010834 // Dismiss any open dialogs.
10835 if (app.crashDialog != null) {
10836 app.crashDialog.dismiss();
10837 app.crashDialog = null;
10838 }
10839 if (app.anrDialog != null) {
10840 app.anrDialog.dismiss();
10841 app.anrDialog = null;
10842 }
10843 if (app.waitDialog != null) {
10844 app.waitDialog.dismiss();
10845 app.waitDialog = null;
10846 }
10847
10848 app.crashing = false;
10849 app.notResponding = false;
10850
10851 app.resetPackageList();
10852 app.thread = null;
10853 app.forcingToForeground = null;
10854 app.foregroundServices = false;
10855
10856 killServicesLocked(app, true);
10857
10858 boolean restart = false;
10859
10860 int NL = mLaunchingProviders.size();
10861
10862 // Remove published content providers.
10863 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010864 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010865 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010866 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010867 cpr.provider = null;
10868 cpr.app = null;
10869
10870 // See if someone is waiting for this provider... in which
10871 // case we don't remove it, but just let it restart.
10872 int i = 0;
10873 if (!app.bad) {
10874 for (; i<NL; i++) {
10875 if (mLaunchingProviders.get(i) == cpr) {
10876 restart = true;
10877 break;
10878 }
10879 }
10880 } else {
10881 i = NL;
10882 }
10883
10884 if (i >= NL) {
10885 removeDyingProviderLocked(app, cpr);
10886 NL = mLaunchingProviders.size();
10887 }
10888 }
10889 app.pubProviders.clear();
10890 }
10891
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010892 // Take care of any launching providers waiting for this process.
10893 if (checkAppInLaunchingProvidersLocked(app, false)) {
10894 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010895 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010897 // Unregister from connected content providers.
10898 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010899 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010900 while (it.hasNext()) {
10901 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10902 cpr.clients.remove(app);
10903 }
10904 app.conProviders.clear();
10905 }
10906
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010907 // At this point there may be remaining entries in mLaunchingProviders
10908 // where we were the only one waiting, so they are no longer of use.
10909 // Look for these and clean up if found.
10910 // XXX Commented out for now. Trying to figure out a way to reproduce
10911 // the actual situation to identify what is actually going on.
10912 if (false) {
10913 for (int i=0; i<NL; i++) {
10914 ContentProviderRecord cpr = (ContentProviderRecord)
10915 mLaunchingProviders.get(i);
10916 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10917 synchronized (cpr) {
10918 cpr.launchingApp = null;
10919 cpr.notifyAll();
10920 }
10921 }
10922 }
10923 }
10924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010925 skipCurrentReceiverLocked(app);
10926
10927 // Unregister any receivers.
10928 if (app.receivers.size() > 0) {
10929 Iterator<ReceiverList> it = app.receivers.iterator();
10930 while (it.hasNext()) {
10931 removeReceiverLocked(it.next());
10932 }
10933 app.receivers.clear();
10934 }
10935
Christopher Tate181fafa2009-05-14 11:12:14 -070010936 // If the app is undergoing backup, tell the backup manager about it
10937 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010938 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010939 try {
10940 IBackupManager bm = IBackupManager.Stub.asInterface(
10941 ServiceManager.getService(Context.BACKUP_SERVICE));
10942 bm.agentDisconnected(app.info.packageName);
10943 } catch (RemoteException e) {
10944 // can't happen; backup manager is local
10945 }
10946 }
10947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 // If the caller is restarting this app, then leave it in its
10949 // current lists and let the caller take care of it.
10950 if (restarting) {
10951 return;
10952 }
10953
10954 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010955 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010956 "Removing non-persistent process during cleanup: " + app);
10957 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010958 if (mHeavyWeightProcess == app) {
10959 mHeavyWeightProcess = null;
10960 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
10961 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010962 } else if (!app.removed) {
10963 // This app is persistent, so we need to keep its record around.
10964 // If it is not already on the pending app list, add it there
10965 // and start a new process for it.
10966 app.thread = null;
10967 app.forcingToForeground = null;
10968 app.foregroundServices = false;
10969 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10970 mPersistentStartingProcesses.add(app);
10971 restart = true;
10972 }
10973 }
10974 mProcessesOnHold.remove(app);
10975
The Android Open Source Project4df24232009-03-05 14:34:35 -080010976 if (app == mHomeProcess) {
10977 mHomeProcess = null;
10978 }
10979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980 if (restart) {
10981 // We have components that still need to be running in the
10982 // process, so re-launch it.
10983 mProcessNames.put(app.processName, app.info.uid, app);
10984 startProcessLocked(app, "restart", app.processName);
10985 } else if (app.pid > 0 && app.pid != MY_PID) {
10986 // Goodbye!
10987 synchronized (mPidsSelfLocked) {
10988 mPidsSelfLocked.remove(app.pid);
10989 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10990 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010991 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992 }
10993 }
10994
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010995 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10996 // Look through the content providers we are waiting to have launched,
10997 // and if any run in this process then either schedule a restart of
10998 // the process or kill the client waiting for it if this process has
10999 // gone bad.
11000 int NL = mLaunchingProviders.size();
11001 boolean restart = false;
11002 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011003 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011004 if (cpr.launchingApp == app) {
11005 if (!alwaysBad && !app.bad) {
11006 restart = true;
11007 } else {
11008 removeDyingProviderLocked(app, cpr);
11009 NL = mLaunchingProviders.size();
11010 }
11011 }
11012 }
11013 return restart;
11014 }
11015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016 // =========================================================
11017 // SERVICES
11018 // =========================================================
11019
11020 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
11021 ActivityManager.RunningServiceInfo info =
11022 new ActivityManager.RunningServiceInfo();
11023 info.service = r.name;
11024 if (r.app != null) {
11025 info.pid = r.app.pid;
11026 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011027 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011028 info.process = r.processName;
11029 info.foreground = r.isForeground;
11030 info.activeSince = r.createTime;
11031 info.started = r.startRequested;
11032 info.clientCount = r.connections.size();
11033 info.crashCount = r.crashCount;
11034 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011035 if (r.isForeground) {
11036 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
11037 }
11038 if (r.startRequested) {
11039 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
11040 }
Dan Egnor42471dd2010-01-07 17:25:22 -080011041 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011042 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
11043 }
11044 if (r.app != null && r.app.persistent) {
11045 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
11046 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011047 for (ConnectionRecord conn : r.connections.values()) {
11048 if (conn.clientLabel != 0) {
11049 info.clientPackage = conn.binding.client.info.packageName;
11050 info.clientLabel = conn.clientLabel;
11051 break;
11052 }
11053 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011054 return info;
11055 }
11056
11057 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
11058 int flags) {
11059 synchronized (this) {
11060 ArrayList<ActivityManager.RunningServiceInfo> res
11061 = new ArrayList<ActivityManager.RunningServiceInfo>();
11062
11063 if (mServices.size() > 0) {
11064 Iterator<ServiceRecord> it = mServices.values().iterator();
11065 while (it.hasNext() && res.size() < maxNum) {
11066 res.add(makeRunningServiceInfoLocked(it.next()));
11067 }
11068 }
11069
11070 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
11071 ServiceRecord r = mRestartingServices.get(i);
11072 ActivityManager.RunningServiceInfo info =
11073 makeRunningServiceInfoLocked(r);
11074 info.restarting = r.nextRestartTime;
11075 res.add(info);
11076 }
11077
11078 return res;
11079 }
11080 }
11081
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011082 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
11083 synchronized (this) {
11084 ServiceRecord r = mServices.get(name);
11085 if (r != null) {
11086 for (ConnectionRecord conn : r.connections.values()) {
11087 if (conn.clientIntent != null) {
11088 return conn.clientIntent;
11089 }
11090 }
11091 }
11092 }
11093 return null;
11094 }
11095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011096 private final ServiceRecord findServiceLocked(ComponentName name,
11097 IBinder token) {
11098 ServiceRecord r = mServices.get(name);
11099 return r == token ? r : null;
11100 }
11101
11102 private final class ServiceLookupResult {
11103 final ServiceRecord record;
11104 final String permission;
11105
11106 ServiceLookupResult(ServiceRecord _record, String _permission) {
11107 record = _record;
11108 permission = _permission;
11109 }
11110 };
11111
11112 private ServiceLookupResult findServiceLocked(Intent service,
11113 String resolvedType) {
11114 ServiceRecord r = null;
11115 if (service.getComponent() != null) {
11116 r = mServices.get(service.getComponent());
11117 }
11118 if (r == null) {
11119 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11120 r = mServicesByIntent.get(filter);
11121 }
11122
11123 if (r == null) {
11124 try {
11125 ResolveInfo rInfo =
11126 ActivityThread.getPackageManager().resolveService(
11127 service, resolvedType, 0);
11128 ServiceInfo sInfo =
11129 rInfo != null ? rInfo.serviceInfo : null;
11130 if (sInfo == null) {
11131 return null;
11132 }
11133
11134 ComponentName name = new ComponentName(
11135 sInfo.applicationInfo.packageName, sInfo.name);
11136 r = mServices.get(name);
11137 } catch (RemoteException ex) {
11138 // pm is in same process, this will never happen.
11139 }
11140 }
11141 if (r != null) {
11142 int callingPid = Binder.getCallingPid();
11143 int callingUid = Binder.getCallingUid();
11144 if (checkComponentPermission(r.permission,
11145 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11146 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011147 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011148 + " from pid=" + callingPid
11149 + ", uid=" + callingUid
11150 + " requires " + r.permission);
11151 return new ServiceLookupResult(null, r.permission);
11152 }
11153 return new ServiceLookupResult(r, null);
11154 }
11155 return null;
11156 }
11157
11158 private class ServiceRestarter implements Runnable {
11159 private ServiceRecord mService;
11160
11161 void setService(ServiceRecord service) {
11162 mService = service;
11163 }
11164
11165 public void run() {
11166 synchronized(ActivityManagerService.this) {
11167 performServiceRestartLocked(mService);
11168 }
11169 }
11170 }
11171
11172 private ServiceLookupResult retrieveServiceLocked(Intent service,
11173 String resolvedType, int callingPid, int callingUid) {
11174 ServiceRecord r = null;
11175 if (service.getComponent() != null) {
11176 r = mServices.get(service.getComponent());
11177 }
11178 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11179 r = mServicesByIntent.get(filter);
11180 if (r == null) {
11181 try {
11182 ResolveInfo rInfo =
11183 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011184 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 ServiceInfo sInfo =
11186 rInfo != null ? rInfo.serviceInfo : null;
11187 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011188 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011189 ": not found");
11190 return null;
11191 }
11192
11193 ComponentName name = new ComponentName(
11194 sInfo.applicationInfo.packageName, sInfo.name);
11195 r = mServices.get(name);
11196 if (r == null) {
11197 filter = new Intent.FilterComparison(service.cloneFilter());
11198 ServiceRestarter res = new ServiceRestarter();
11199 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11200 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11201 synchronized (stats) {
11202 ss = stats.getServiceStatsLocked(
11203 sInfo.applicationInfo.uid, sInfo.packageName,
11204 sInfo.name);
11205 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080011206 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011207 res.setService(r);
11208 mServices.put(name, r);
11209 mServicesByIntent.put(filter, r);
11210
11211 // Make sure this component isn't in the pending list.
11212 int N = mPendingServices.size();
11213 for (int i=0; i<N; i++) {
11214 ServiceRecord pr = mPendingServices.get(i);
11215 if (pr.name.equals(name)) {
11216 mPendingServices.remove(i);
11217 i--;
11218 N--;
11219 }
11220 }
11221 }
11222 } catch (RemoteException ex) {
11223 // pm is in same process, this will never happen.
11224 }
11225 }
11226 if (r != null) {
11227 if (checkComponentPermission(r.permission,
11228 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11229 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011230 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011231 + " from pid=" + Binder.getCallingPid()
11232 + ", uid=" + Binder.getCallingUid()
11233 + " requires " + r.permission);
11234 return new ServiceLookupResult(null, r.permission);
11235 }
11236 return new ServiceLookupResult(r, null);
11237 }
11238 return null;
11239 }
11240
11241 private final void bumpServiceExecutingLocked(ServiceRecord r) {
11242 long now = SystemClock.uptimeMillis();
11243 if (r.executeNesting == 0 && r.app != null) {
11244 if (r.app.executingServices.size() == 0) {
11245 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11246 msg.obj = r.app;
11247 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
11248 }
11249 r.app.executingServices.add(r);
11250 }
11251 r.executeNesting++;
11252 r.executingStart = now;
11253 }
11254
11255 private final void sendServiceArgsLocked(ServiceRecord r,
11256 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011257 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 if (N == 0) {
11259 return;
11260 }
11261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011262 int i = 0;
11263 while (i < N) {
11264 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011265 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011266 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011267 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070011268 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011269 // If somehow we got a dummy start at the front, then
11270 // just drop it here.
11271 i++;
11272 continue;
11273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 bumpServiceExecutingLocked(r);
11275 if (!oomAdjusted) {
11276 oomAdjusted = true;
11277 updateOomAdjLocked(r.app);
11278 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011279 int flags = 0;
11280 if (si.deliveryCount > 0) {
11281 flags |= Service.START_FLAG_RETRY;
11282 }
11283 if (si.doneExecutingCount > 0) {
11284 flags |= Service.START_FLAG_REDELIVERY;
11285 }
11286 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
11287 si.deliveredTime = SystemClock.uptimeMillis();
11288 r.deliveredStarts.add(si);
11289 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011290 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011291 } catch (RemoteException e) {
11292 // Remote process gone... we'll let the normal cleanup take
11293 // care of this.
11294 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011296 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011297 break;
11298 }
11299 }
11300 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011301 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011302 } else {
11303 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011304 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011305 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011306 }
11307 }
11308 }
11309
11310 private final boolean requestServiceBindingLocked(ServiceRecord r,
11311 IntentBindRecord i, boolean rebind) {
11312 if (r.app == null || r.app.thread == null) {
11313 // If service is not currently running, can't yet bind.
11314 return false;
11315 }
11316 if ((!i.requested || rebind) && i.apps.size() > 0) {
11317 try {
11318 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011319 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011320 + ": shouldUnbind=" + i.hasBound);
11321 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11322 if (!rebind) {
11323 i.requested = true;
11324 }
11325 i.hasBound = true;
11326 i.doRebind = false;
11327 } catch (RemoteException e) {
11328 return false;
11329 }
11330 }
11331 return true;
11332 }
11333
11334 private final void requestServiceBindingsLocked(ServiceRecord r) {
11335 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11336 while (bindings.hasNext()) {
11337 IntentBindRecord i = bindings.next();
11338 if (!requestServiceBindingLocked(r, i, false)) {
11339 break;
11340 }
11341 }
11342 }
11343
11344 private final void realStartServiceLocked(ServiceRecord r,
11345 ProcessRecord app) throws RemoteException {
11346 if (app.thread == null) {
11347 throw new RemoteException();
11348 }
11349
11350 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011351 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011352
11353 app.services.add(r);
11354 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011355 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011356
11357 boolean created = false;
11358 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011359 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011361 mStringBuilder.setLength(0);
11362 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011363 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011364 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011365 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011366 synchronized (r.stats.getBatteryStats()) {
11367 r.stats.startLaunchedLocked();
11368 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011369 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011371 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011372 created = true;
11373 } finally {
11374 if (!created) {
11375 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011376 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011377 }
11378 }
11379
11380 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011381
11382 // If the service is in the started state, and there are no
11383 // pending arguments, then fake up one so its onStartCommand() will
11384 // be called.
11385 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11386 r.lastStartId++;
11387 if (r.lastStartId < 1) {
11388 r.lastStartId = 1;
11389 }
11390 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11391 }
11392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011393 sendServiceArgsLocked(r, true);
11394 }
11395
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011396 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11397 boolean allowCancel) {
11398 boolean canceled = false;
11399
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011400 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011401 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011402 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011403
11404 // Any delivered but not yet finished starts should be put back
11405 // on the pending list.
11406 final int N = r.deliveredStarts.size();
11407 if (N > 0) {
11408 for (int i=N-1; i>=0; i--) {
11409 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11410 if (si.intent == null) {
11411 // We'll generate this again if needed.
11412 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11413 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11414 r.pendingStarts.add(0, si);
11415 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11416 dur *= 2;
11417 if (minDuration < dur) minDuration = dur;
11418 if (resetTime < dur) resetTime = dur;
11419 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011420 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011421 + r.name);
11422 canceled = true;
11423 }
11424 }
11425 r.deliveredStarts.clear();
11426 }
11427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011428 r.totalRestartCount++;
11429 if (r.restartDelay == 0) {
11430 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011431 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432 } else {
11433 // If it has been a "reasonably long time" since the service
11434 // was started, then reset our restart duration back to
11435 // the beginning, so we don't infinitely increase the duration
11436 // on a service that just occasionally gets killed (which is
11437 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011438 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011439 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011440 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011441 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011442 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011443 if (r.restartDelay < minDuration) {
11444 r.restartDelay = minDuration;
11445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011446 }
11447 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011448
11449 r.nextRestartTime = now + r.restartDelay;
11450
11451 // Make sure that we don't end up restarting a bunch of services
11452 // all at the same time.
11453 boolean repeat;
11454 do {
11455 repeat = false;
11456 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11457 ServiceRecord r2 = mRestartingServices.get(i);
11458 if (r2 != r && r.nextRestartTime
11459 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11460 && r.nextRestartTime
11461 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11462 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11463 r.restartDelay = r.nextRestartTime - now;
11464 repeat = true;
11465 break;
11466 }
11467 }
11468 } while (repeat);
11469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 if (!mRestartingServices.contains(r)) {
11471 mRestartingServices.add(r);
11472 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011473
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011474 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011476 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011477 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011478 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011479 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011480 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011481 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011482 r.shortName, r.restartDelay);
11483
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011484 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 }
11486
11487 final void performServiceRestartLocked(ServiceRecord r) {
11488 if (!mRestartingServices.contains(r)) {
11489 return;
11490 }
11491 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11492 }
11493
11494 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11495 if (r.restartDelay == 0) {
11496 return false;
11497 }
11498 r.resetRestartCounter();
11499 mRestartingServices.remove(r);
11500 mHandler.removeCallbacks(r.restarter);
11501 return true;
11502 }
11503
11504 private final boolean bringUpServiceLocked(ServiceRecord r,
11505 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011506 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011507 //r.dump(" ");
11508
Dianne Hackborn36124872009-10-08 16:22:03 -070011509 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011510 sendServiceArgsLocked(r, false);
11511 return true;
11512 }
11513
11514 if (!whileRestarting && r.restartDelay > 0) {
11515 // If waiting for a restart, then do nothing.
11516 return true;
11517 }
11518
Joe Onorato8a9b2202010-02-26 18:56:32 -080011519 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011520 + " " + r.intent);
11521
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011522 // We are now bringing the service up, so no longer in the
11523 // restarting state.
11524 mRestartingServices.remove(r);
11525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011526 final String appName = r.processName;
11527 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11528 if (app != null && app.thread != null) {
11529 try {
11530 realStartServiceLocked(r, app);
11531 return true;
11532 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011533 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011534 }
11535
11536 // If a dead object exception was thrown -- fall through to
11537 // restart the application.
11538 }
11539
Dianne Hackborn36124872009-10-08 16:22:03 -070011540 // Not running -- get it started, and enqueue this service record
11541 // to be executed when the app comes up.
11542 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11543 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011544 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011545 + r.appInfo.packageName + "/"
11546 + r.appInfo.uid + " for service "
11547 + r.intent.getIntent() + ": process is bad");
11548 bringDownServiceLocked(r, true);
11549 return false;
11550 }
11551
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011552 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011553 mPendingServices.add(r);
11554 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011556 return true;
11557 }
11558
11559 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011560 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011561 //r.dump(" ");
11562
11563 // Does it still need to run?
11564 if (!force && r.startRequested) {
11565 return;
11566 }
11567 if (r.connections.size() > 0) {
11568 if (!force) {
11569 // XXX should probably keep a count of the number of auto-create
11570 // connections directly in the service.
11571 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11572 while (it.hasNext()) {
11573 ConnectionRecord cr = it.next();
11574 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11575 return;
11576 }
11577 }
11578 }
11579
11580 // Report to all of the connections that the service is no longer
11581 // available.
11582 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11583 while (it.hasNext()) {
11584 ConnectionRecord c = it.next();
11585 try {
11586 // todo: shouldn't be a synchronous call!
11587 c.conn.connected(r.name, null);
11588 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011589 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011590 " to connection " + c.conn.asBinder() +
11591 " (in " + c.binding.client.processName + ")", e);
11592 }
11593 }
11594 }
11595
11596 // Tell the service that it has been unbound.
11597 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11598 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11599 while (it.hasNext()) {
11600 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011601 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011602 + ": hasBound=" + ibr.hasBound);
11603 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11604 try {
11605 bumpServiceExecutingLocked(r);
11606 updateOomAdjLocked(r.app);
11607 ibr.hasBound = false;
11608 r.app.thread.scheduleUnbindService(r,
11609 ibr.intent.getIntent());
11610 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011611 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011612 + r.shortName, e);
11613 serviceDoneExecutingLocked(r, true);
11614 }
11615 }
11616 }
11617 }
11618
Joe Onorato8a9b2202010-02-26 18:56:32 -080011619 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011621 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011622 System.identityHashCode(r), r.shortName,
11623 (r.app != null) ? r.app.pid : -1);
11624
11625 mServices.remove(r.name);
11626 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011627 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628 r.totalRestartCount = 0;
11629 unscheduleServiceRestartLocked(r);
11630
11631 // Also make sure it is not on the pending list.
11632 int N = mPendingServices.size();
11633 for (int i=0; i<N; i++) {
11634 if (mPendingServices.get(i) == r) {
11635 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011636 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011637 TAG, "Removed pending service: " + r.shortName);
11638 i--;
11639 N--;
11640 }
11641 }
11642
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011643 r.cancelNotification();
11644 r.isForeground = false;
11645 r.foregroundId = 0;
11646 r.foregroundNoti = null;
11647
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011648 // Clear start entries.
11649 r.deliveredStarts.clear();
11650 r.pendingStarts.clear();
11651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011652 if (r.app != null) {
11653 synchronized (r.stats.getBatteryStats()) {
11654 r.stats.stopLaunchedLocked();
11655 }
11656 r.app.services.remove(r);
11657 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011658 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011659 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011660 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011661 bumpServiceExecutingLocked(r);
11662 mStoppingServices.add(r);
11663 updateOomAdjLocked(r.app);
11664 r.app.thread.scheduleStopService(r);
11665 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011666 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011667 + r.shortName, e);
11668 serviceDoneExecutingLocked(r, true);
11669 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011670 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011671 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011672 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 TAG, "Removed service that has no process: " + r.shortName);
11674 }
11675 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011676 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011677 TAG, "Removed service that is not running: " + r.shortName);
11678 }
11679 }
11680
11681 ComponentName startServiceLocked(IApplicationThread caller,
11682 Intent service, String resolvedType,
11683 int callingPid, int callingUid) {
11684 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011685 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011686 + " type=" + resolvedType + " args=" + service.getExtras());
11687
11688 if (caller != null) {
11689 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11690 if (callerApp == null) {
11691 throw new SecurityException(
11692 "Unable to find app for caller " + caller
11693 + " (pid=" + Binder.getCallingPid()
11694 + ") when starting service " + service);
11695 }
11696 }
11697
11698 ServiceLookupResult res =
11699 retrieveServiceLocked(service, resolvedType,
11700 callingPid, callingUid);
11701 if (res == null) {
11702 return null;
11703 }
11704 if (res.record == null) {
11705 return new ComponentName("!", res.permission != null
11706 ? res.permission : "private to package");
11707 }
11708 ServiceRecord r = res.record;
11709 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011710 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011711 + r.shortName);
11712 }
11713 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011714 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011715 r.lastStartId++;
11716 if (r.lastStartId < 1) {
11717 r.lastStartId = 1;
11718 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011719 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011720 r.lastActivity = SystemClock.uptimeMillis();
11721 synchronized (r.stats.getBatteryStats()) {
11722 r.stats.startRunningLocked();
11723 }
11724 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11725 return new ComponentName("!", "Service process is bad");
11726 }
11727 return r.name;
11728 }
11729 }
11730
11731 public ComponentName startService(IApplicationThread caller, Intent service,
11732 String resolvedType) {
11733 // Refuse possible leaked file descriptors
11734 if (service != null && service.hasFileDescriptors() == true) {
11735 throw new IllegalArgumentException("File descriptors passed in Intent");
11736 }
11737
11738 synchronized(this) {
11739 final int callingPid = Binder.getCallingPid();
11740 final int callingUid = Binder.getCallingUid();
11741 final long origId = Binder.clearCallingIdentity();
11742 ComponentName res = startServiceLocked(caller, service,
11743 resolvedType, callingPid, callingUid);
11744 Binder.restoreCallingIdentity(origId);
11745 return res;
11746 }
11747 }
11748
11749 ComponentName startServiceInPackage(int uid,
11750 Intent service, String resolvedType) {
11751 synchronized(this) {
11752 final long origId = Binder.clearCallingIdentity();
11753 ComponentName res = startServiceLocked(null, service,
11754 resolvedType, -1, uid);
11755 Binder.restoreCallingIdentity(origId);
11756 return res;
11757 }
11758 }
11759
11760 public int stopService(IApplicationThread caller, Intent service,
11761 String resolvedType) {
11762 // Refuse possible leaked file descriptors
11763 if (service != null && service.hasFileDescriptors() == true) {
11764 throw new IllegalArgumentException("File descriptors passed in Intent");
11765 }
11766
11767 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011768 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011769 + " type=" + resolvedType);
11770
11771 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11772 if (caller != null && callerApp == null) {
11773 throw new SecurityException(
11774 "Unable to find app for caller " + caller
11775 + " (pid=" + Binder.getCallingPid()
11776 + ") when stopping service " + service);
11777 }
11778
11779 // If this service is active, make sure it is stopped.
11780 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11781 if (r != null) {
11782 if (r.record != null) {
11783 synchronized (r.record.stats.getBatteryStats()) {
11784 r.record.stats.stopRunningLocked();
11785 }
11786 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011787 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011788 final long origId = Binder.clearCallingIdentity();
11789 bringDownServiceLocked(r.record, false);
11790 Binder.restoreCallingIdentity(origId);
11791 return 1;
11792 }
11793 return -1;
11794 }
11795 }
11796
11797 return 0;
11798 }
11799
11800 public IBinder peekService(Intent service, String resolvedType) {
11801 // Refuse possible leaked file descriptors
11802 if (service != null && service.hasFileDescriptors() == true) {
11803 throw new IllegalArgumentException("File descriptors passed in Intent");
11804 }
11805
11806 IBinder ret = null;
11807
11808 synchronized(this) {
11809 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11810
11811 if (r != null) {
11812 // r.record is null if findServiceLocked() failed the caller permission check
11813 if (r.record == null) {
11814 throw new SecurityException(
11815 "Permission Denial: Accessing service " + r.record.name
11816 + " from pid=" + Binder.getCallingPid()
11817 + ", uid=" + Binder.getCallingUid()
11818 + " requires " + r.permission);
11819 }
11820 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11821 if (ib != null) {
11822 ret = ib.binder;
11823 }
11824 }
11825 }
11826
11827 return ret;
11828 }
11829
11830 public boolean stopServiceToken(ComponentName className, IBinder token,
11831 int startId) {
11832 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011833 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011834 + " " + token + " startId=" + startId);
11835 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011836 if (r != null) {
11837 if (startId >= 0) {
11838 // Asked to only stop if done with all work. Note that
11839 // to avoid leaks, we will take this as dropping all
11840 // start items up to and including this one.
11841 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11842 if (si != null) {
11843 while (r.deliveredStarts.size() > 0) {
11844 if (r.deliveredStarts.remove(0) == si) {
11845 break;
11846 }
11847 }
11848 }
11849
11850 if (r.lastStartId != startId) {
11851 return false;
11852 }
11853
11854 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011855 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011856 + " is last, but have " + r.deliveredStarts.size()
11857 + " remaining args");
11858 }
11859 }
11860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011861 synchronized (r.stats.getBatteryStats()) {
11862 r.stats.stopRunningLocked();
11863 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011864 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011865 }
11866 final long origId = Binder.clearCallingIdentity();
11867 bringDownServiceLocked(r, false);
11868 Binder.restoreCallingIdentity(origId);
11869 return true;
11870 }
11871 }
11872 return false;
11873 }
11874
11875 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011876 int id, Notification notification, boolean removeNotification) {
11877 final long origId = Binder.clearCallingIdentity();
11878 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011879 synchronized(this) {
11880 ServiceRecord r = findServiceLocked(className, token);
11881 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011882 if (id != 0) {
11883 if (notification == null) {
11884 throw new IllegalArgumentException("null notification");
11885 }
11886 if (r.foregroundId != id) {
11887 r.cancelNotification();
11888 r.foregroundId = id;
11889 }
11890 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11891 r.foregroundNoti = notification;
11892 r.isForeground = true;
11893 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011894 if (r.app != null) {
11895 updateServiceForegroundLocked(r.app, true);
11896 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011897 } else {
11898 if (r.isForeground) {
11899 r.isForeground = false;
11900 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011901 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011902 updateServiceForegroundLocked(r.app, true);
11903 }
11904 }
11905 if (removeNotification) {
11906 r.cancelNotification();
11907 r.foregroundId = 0;
11908 r.foregroundNoti = null;
11909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011910 }
11911 }
11912 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011913 } finally {
11914 Binder.restoreCallingIdentity(origId);
11915 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011916 }
11917
11918 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11919 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070011920 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011921 if (sr.isForeground) {
11922 anyForeground = true;
11923 break;
11924 }
11925 }
11926 if (anyForeground != proc.foregroundServices) {
11927 proc.foregroundServices = anyForeground;
11928 if (oomAdj) {
11929 updateOomAdjLocked();
11930 }
11931 }
11932 }
11933
11934 public int bindService(IApplicationThread caller, IBinder token,
11935 Intent service, String resolvedType,
11936 IServiceConnection connection, int flags) {
11937 // Refuse possible leaked file descriptors
11938 if (service != null && service.hasFileDescriptors() == true) {
11939 throw new IllegalArgumentException("File descriptors passed in Intent");
11940 }
11941
11942 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011943 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011944 + " type=" + resolvedType + " conn=" + connection.asBinder()
11945 + " flags=0x" + Integer.toHexString(flags));
11946 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11947 if (callerApp == null) {
11948 throw new SecurityException(
11949 "Unable to find app for caller " + caller
11950 + " (pid=" + Binder.getCallingPid()
11951 + ") when binding service " + service);
11952 }
11953
11954 HistoryRecord activity = null;
11955 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011956 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011957 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011958 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011959 return 0;
11960 }
11961 activity = (HistoryRecord)mHistory.get(aindex);
11962 }
11963
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011964 int clientLabel = 0;
11965 PendingIntent clientIntent = null;
11966
11967 if (callerApp.info.uid == Process.SYSTEM_UID) {
11968 // Hacky kind of thing -- allow system stuff to tell us
11969 // what they are, so we can report this elsewhere for
11970 // others to know why certain services are running.
11971 try {
11972 clientIntent = (PendingIntent)service.getParcelableExtra(
11973 Intent.EXTRA_CLIENT_INTENT);
11974 } catch (RuntimeException e) {
11975 }
11976 if (clientIntent != null) {
11977 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11978 if (clientLabel != 0) {
11979 // There are no useful extras in the intent, trash them.
11980 // System code calling with this stuff just needs to know
11981 // this will happen.
11982 service = service.cloneFilter();
11983 }
11984 }
11985 }
11986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011987 ServiceLookupResult res =
11988 retrieveServiceLocked(service, resolvedType,
11989 Binder.getCallingPid(), Binder.getCallingUid());
11990 if (res == null) {
11991 return 0;
11992 }
11993 if (res.record == null) {
11994 return -1;
11995 }
11996 ServiceRecord s = res.record;
11997
11998 final long origId = Binder.clearCallingIdentity();
11999
12000 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012001 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012002 + s.shortName);
12003 }
12004
12005 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
12006 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012007 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012008
12009 IBinder binder = connection.asBinder();
12010 s.connections.put(binder, c);
12011 b.connections.add(c);
12012 if (activity != null) {
12013 if (activity.connections == null) {
12014 activity.connections = new HashSet<ConnectionRecord>();
12015 }
12016 activity.connections.add(c);
12017 }
12018 b.client.connections.add(c);
12019 mServiceConnections.put(binder, c);
12020
12021 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
12022 s.lastActivity = SystemClock.uptimeMillis();
12023 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
12024 return 0;
12025 }
12026 }
12027
12028 if (s.app != null) {
12029 // This could have made the service more important.
12030 updateOomAdjLocked(s.app);
12031 }
12032
Joe Onorato8a9b2202010-02-26 18:56:32 -080012033 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012034 + ": received=" + b.intent.received
12035 + " apps=" + b.intent.apps.size()
12036 + " doRebind=" + b.intent.doRebind);
12037
12038 if (s.app != null && b.intent.received) {
12039 // Service is already running, so we can immediately
12040 // publish the connection.
12041 try {
12042 c.conn.connected(s.name, b.intent.binder);
12043 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012044 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012045 + " to connection " + c.conn.asBinder()
12046 + " (in " + c.binding.client.processName + ")", e);
12047 }
12048
12049 // If this is the first app connected back to this binding,
12050 // and the service had previously asked to be told when
12051 // rebound, then do so.
12052 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
12053 requestServiceBindingLocked(s, b.intent, true);
12054 }
12055 } else if (!b.intent.requested) {
12056 requestServiceBindingLocked(s, b.intent, false);
12057 }
12058
12059 Binder.restoreCallingIdentity(origId);
12060 }
12061
12062 return 1;
12063 }
12064
12065 private void removeConnectionLocked(
12066 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
12067 IBinder binder = c.conn.asBinder();
12068 AppBindRecord b = c.binding;
12069 ServiceRecord s = b.service;
12070 s.connections.remove(binder);
12071 b.connections.remove(c);
12072 if (c.activity != null && c.activity != skipAct) {
12073 if (c.activity.connections != null) {
12074 c.activity.connections.remove(c);
12075 }
12076 }
12077 if (b.client != skipApp) {
12078 b.client.connections.remove(c);
12079 }
12080 mServiceConnections.remove(binder);
12081
12082 if (b.connections.size() == 0) {
12083 b.intent.apps.remove(b.client);
12084 }
12085
Joe Onorato8a9b2202010-02-26 18:56:32 -080012086 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012087 + ": shouldUnbind=" + b.intent.hasBound);
12088 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
12089 && b.intent.hasBound) {
12090 try {
12091 bumpServiceExecutingLocked(s);
12092 updateOomAdjLocked(s.app);
12093 b.intent.hasBound = false;
12094 // Assume the client doesn't want to know about a rebind;
12095 // we will deal with that later if it asks for one.
12096 b.intent.doRebind = false;
12097 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
12098 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012099 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012100 serviceDoneExecutingLocked(s, true);
12101 }
12102 }
12103
12104 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
12105 bringDownServiceLocked(s, false);
12106 }
12107 }
12108
12109 public boolean unbindService(IServiceConnection connection) {
12110 synchronized (this) {
12111 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012112 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012113 ConnectionRecord r = mServiceConnections.get(binder);
12114 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012115 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012116 + connection.asBinder());
12117 return false;
12118 }
12119
12120 final long origId = Binder.clearCallingIdentity();
12121
12122 removeConnectionLocked(r, null, null);
12123
12124 if (r.binding.service.app != null) {
12125 // This could have made the service less important.
12126 updateOomAdjLocked(r.binding.service.app);
12127 }
12128
12129 Binder.restoreCallingIdentity(origId);
12130 }
12131
12132 return true;
12133 }
12134
12135 public void publishService(IBinder token, Intent intent, IBinder service) {
12136 // Refuse possible leaked file descriptors
12137 if (intent != null && intent.hasFileDescriptors() == true) {
12138 throw new IllegalArgumentException("File descriptors passed in Intent");
12139 }
12140
12141 synchronized(this) {
12142 if (!(token instanceof ServiceRecord)) {
12143 throw new IllegalArgumentException("Invalid service token");
12144 }
12145 ServiceRecord r = (ServiceRecord)token;
12146
12147 final long origId = Binder.clearCallingIdentity();
12148
Joe Onorato8a9b2202010-02-26 18:56:32 -080012149 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012150 + " " + intent + ": " + service);
12151 if (r != null) {
12152 Intent.FilterComparison filter
12153 = new Intent.FilterComparison(intent);
12154 IntentBindRecord b = r.bindings.get(filter);
12155 if (b != null && !b.received) {
12156 b.binder = service;
12157 b.requested = true;
12158 b.received = true;
12159 if (r.connections.size() > 0) {
12160 Iterator<ConnectionRecord> it
12161 = r.connections.values().iterator();
12162 while (it.hasNext()) {
12163 ConnectionRecord c = it.next();
12164 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012165 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012166 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012167 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012168 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012169 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012170 TAG, "Published intent: " + intent);
12171 continue;
12172 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012173 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012174 try {
12175 c.conn.connected(r.name, service);
12176 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012177 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012178 " to connection " + c.conn.asBinder() +
12179 " (in " + c.binding.client.processName + ")", e);
12180 }
12181 }
12182 }
12183 }
12184
12185 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12186
12187 Binder.restoreCallingIdentity(origId);
12188 }
12189 }
12190 }
12191
12192 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
12193 // Refuse possible leaked file descriptors
12194 if (intent != null && intent.hasFileDescriptors() == true) {
12195 throw new IllegalArgumentException("File descriptors passed in Intent");
12196 }
12197
12198 synchronized(this) {
12199 if (!(token instanceof ServiceRecord)) {
12200 throw new IllegalArgumentException("Invalid service token");
12201 }
12202 ServiceRecord r = (ServiceRecord)token;
12203
12204 final long origId = Binder.clearCallingIdentity();
12205
12206 if (r != null) {
12207 Intent.FilterComparison filter
12208 = new Intent.FilterComparison(intent);
12209 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012210 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012211 + " at " + b + ": apps="
12212 + (b != null ? b.apps.size() : 0));
12213 if (b != null) {
12214 if (b.apps.size() > 0) {
12215 // Applications have already bound since the last
12216 // unbind, so just rebind right here.
12217 requestServiceBindingLocked(r, b, true);
12218 } else {
12219 // Note to tell the service the next time there is
12220 // a new client.
12221 b.doRebind = true;
12222 }
12223 }
12224
12225 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12226
12227 Binder.restoreCallingIdentity(origId);
12228 }
12229 }
12230 }
12231
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012232 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012233 synchronized(this) {
12234 if (!(token instanceof ServiceRecord)) {
12235 throw new IllegalArgumentException("Invalid service token");
12236 }
12237 ServiceRecord r = (ServiceRecord)token;
12238 boolean inStopping = mStoppingServices.contains(token);
12239 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012240 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012241 + ": nesting=" + r.executeNesting
12242 + ", inStopping=" + inStopping);
12243 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012244 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012245 + " with incorrect token: given " + token
12246 + ", expected " + r);
12247 return;
12248 }
12249
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012250 if (type == 1) {
12251 // This is a call from a service start... take care of
12252 // book-keeping.
12253 r.callStart = true;
12254 switch (res) {
12255 case Service.START_STICKY_COMPATIBILITY:
12256 case Service.START_STICKY: {
12257 // We are done with the associated start arguments.
12258 r.findDeliveredStart(startId, true);
12259 // Don't stop if killed.
12260 r.stopIfKilled = false;
12261 break;
12262 }
12263 case Service.START_NOT_STICKY: {
12264 // We are done with the associated start arguments.
12265 r.findDeliveredStart(startId, true);
12266 if (r.lastStartId == startId) {
12267 // There is no more work, and this service
12268 // doesn't want to hang around if killed.
12269 r.stopIfKilled = true;
12270 }
12271 break;
12272 }
12273 case Service.START_REDELIVER_INTENT: {
12274 // We'll keep this item until they explicitly
12275 // call stop for it, but keep track of the fact
12276 // that it was delivered.
12277 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12278 if (si != null) {
12279 si.deliveryCount = 0;
12280 si.doneExecutingCount++;
12281 // Don't stop if killed.
12282 r.stopIfKilled = true;
12283 }
12284 break;
12285 }
12286 default:
12287 throw new IllegalArgumentException(
12288 "Unknown service start result: " + res);
12289 }
12290 if (res == Service.START_STICKY_COMPATIBILITY) {
12291 r.callStart = false;
12292 }
12293 }
12294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012295 final long origId = Binder.clearCallingIdentity();
12296 serviceDoneExecutingLocked(r, inStopping);
12297 Binder.restoreCallingIdentity(origId);
12298 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012299 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012300 + " with token " + token);
12301 }
12302 }
12303 }
12304
12305 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
12306 r.executeNesting--;
12307 if (r.executeNesting <= 0 && r.app != null) {
12308 r.app.executingServices.remove(r);
12309 if (r.app.executingServices.size() == 0) {
12310 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
12311 }
12312 if (inStopping) {
12313 mStoppingServices.remove(r);
12314 }
12315 updateOomAdjLocked(r.app);
12316 }
12317 }
12318
12319 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012320 String anrMessage = null;
12321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012322 synchronized(this) {
12323 if (proc.executingServices.size() == 0 || proc.thread == null) {
12324 return;
12325 }
12326 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12327 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12328 ServiceRecord timeout = null;
12329 long nextTime = 0;
12330 while (it.hasNext()) {
12331 ServiceRecord sr = it.next();
12332 if (sr.executingStart < maxTime) {
12333 timeout = sr;
12334 break;
12335 }
12336 if (sr.executingStart > nextTime) {
12337 nextTime = sr.executingStart;
12338 }
12339 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012340 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012341 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012342 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012343 } else {
12344 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12345 msg.obj = proc;
12346 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12347 }
12348 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012349
12350 if (anrMessage != null) {
12351 appNotResponding(proc, null, null, anrMessage);
12352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012353 }
12354
12355 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012356 // BACKUP AND RESTORE
12357 // =========================================================
12358
12359 // Cause the target app to be launched if necessary and its backup agent
12360 // instantiated. The backup agent will invoke backupAgentCreated() on the
12361 // activity manager to announce its creation.
12362 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012363 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012364 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12365
12366 synchronized(this) {
12367 // !!! TODO: currently no check here that we're already bound
12368 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12369 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12370 synchronized (stats) {
12371 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12372 }
12373
12374 BackupRecord r = new BackupRecord(ss, app, backupMode);
12375 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12376 // startProcessLocked() returns existing proc's record if it's already running
12377 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012378 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012379 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012380 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012381 return false;
12382 }
12383
12384 r.app = proc;
12385 mBackupTarget = r;
12386 mBackupAppName = app.packageName;
12387
Christopher Tate6fa95972009-06-05 18:43:55 -070012388 // Try not to kill the process during backup
12389 updateOomAdjLocked(proc);
12390
Christopher Tate181fafa2009-05-14 11:12:14 -070012391 // If the process is already attached, schedule the creation of the backup agent now.
12392 // If it is not yet live, this will be done when it attaches to the framework.
12393 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012394 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012395 try {
12396 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12397 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012398 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012399 }
12400 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012401 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012402 }
12403 // Invariants: at this point, the target app process exists and the application
12404 // is either already running or in the process of coming up. mBackupTarget and
12405 // mBackupAppName describe the app, so that when it binds back to the AM we
12406 // know that it's scheduled for a backup-agent operation.
12407 }
12408
12409 return true;
12410 }
12411
12412 // A backup agent has just come up
12413 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012414 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012415 + " = " + agent);
12416
12417 synchronized(this) {
12418 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012419 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012420 return;
12421 }
12422
Christopher Tate043dadc2009-06-02 16:11:00 -070012423 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012424 try {
12425 IBackupManager bm = IBackupManager.Stub.asInterface(
12426 ServiceManager.getService(Context.BACKUP_SERVICE));
12427 bm.agentConnected(agentPackageName, agent);
12428 } catch (RemoteException e) {
12429 // can't happen; the backup manager service is local
12430 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012431 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012432 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012433 } finally {
12434 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012435 }
12436 }
12437 }
12438
12439 // done with this agent
12440 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012441 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012442 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012443 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012444 return;
12445 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012446
12447 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012448 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012449 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012450 return;
12451 }
12452
Christopher Tate181fafa2009-05-14 11:12:14 -070012453 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012454 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012455 return;
12456 }
12457
Christopher Tate6fa95972009-06-05 18:43:55 -070012458 ProcessRecord proc = mBackupTarget.app;
12459 mBackupTarget = null;
12460 mBackupAppName = null;
12461
12462 // Not backing this app up any more; reset its OOM adjustment
12463 updateOomAdjLocked(proc);
12464
Christopher Tatec7b31e32009-06-10 15:49:30 -070012465 // If the app crashed during backup, 'thread' will be null here
12466 if (proc.thread != null) {
12467 try {
12468 proc.thread.scheduleDestroyBackupAgent(appInfo);
12469 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012470 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012471 e.printStackTrace();
12472 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012473 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012474 }
12475 }
12476 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012477 // BROADCASTS
12478 // =========================================================
12479
Josh Bartel7f208742010-02-25 11:01:44 -060012480 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012481 List cur) {
12482 final ContentResolver resolver = mContext.getContentResolver();
12483 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12484 if (list == null) {
12485 return cur;
12486 }
12487 int N = list.size();
12488 for (int i=0; i<N; i++) {
12489 Intent intent = list.get(i);
12490 if (filter.match(resolver, intent, true, TAG) >= 0) {
12491 if (cur == null) {
12492 cur = new ArrayList<Intent>();
12493 }
12494 cur.add(intent);
12495 }
12496 }
12497 return cur;
12498 }
12499
12500 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012501 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012502 + mBroadcastsScheduled);
12503
12504 if (mBroadcastsScheduled) {
12505 return;
12506 }
12507 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12508 mBroadcastsScheduled = true;
12509 }
12510
12511 public Intent registerReceiver(IApplicationThread caller,
12512 IIntentReceiver receiver, IntentFilter filter, String permission) {
12513 synchronized(this) {
12514 ProcessRecord callerApp = null;
12515 if (caller != null) {
12516 callerApp = getRecordForAppLocked(caller);
12517 if (callerApp == null) {
12518 throw new SecurityException(
12519 "Unable to find app for caller " + caller
12520 + " (pid=" + Binder.getCallingPid()
12521 + ") when registering receiver " + receiver);
12522 }
12523 }
12524
12525 List allSticky = null;
12526
12527 // Look for any matching sticky broadcasts...
12528 Iterator actions = filter.actionsIterator();
12529 if (actions != null) {
12530 while (actions.hasNext()) {
12531 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012532 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012533 }
12534 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012535 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012536 }
12537
12538 // The first sticky in the list is returned directly back to
12539 // the client.
12540 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12541
Joe Onorato8a9b2202010-02-26 18:56:32 -080012542 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012543 + ": " + sticky);
12544
12545 if (receiver == null) {
12546 return sticky;
12547 }
12548
12549 ReceiverList rl
12550 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12551 if (rl == null) {
12552 rl = new ReceiverList(this, callerApp,
12553 Binder.getCallingPid(),
12554 Binder.getCallingUid(), receiver);
12555 if (rl.app != null) {
12556 rl.app.receivers.add(rl);
12557 } else {
12558 try {
12559 receiver.asBinder().linkToDeath(rl, 0);
12560 } catch (RemoteException e) {
12561 return sticky;
12562 }
12563 rl.linkedToDeath = true;
12564 }
12565 mRegisteredReceivers.put(receiver.asBinder(), rl);
12566 }
12567 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12568 rl.add(bf);
12569 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012570 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012571 }
12572 mReceiverResolver.addFilter(bf);
12573
12574 // Enqueue broadcasts for all existing stickies that match
12575 // this filter.
12576 if (allSticky != null) {
12577 ArrayList receivers = new ArrayList();
12578 receivers.add(bf);
12579
12580 int N = allSticky.size();
12581 for (int i=0; i<N; i++) {
12582 Intent intent = (Intent)allSticky.get(i);
12583 BroadcastRecord r = new BroadcastRecord(intent, null,
12584 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012585 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012586 if (mParallelBroadcasts.size() == 0) {
12587 scheduleBroadcastsLocked();
12588 }
12589 mParallelBroadcasts.add(r);
12590 }
12591 }
12592
12593 return sticky;
12594 }
12595 }
12596
12597 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012598 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012599
12600 boolean doNext = false;
12601
12602 synchronized(this) {
12603 ReceiverList rl
12604 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12605 if (rl != null) {
12606 if (rl.curBroadcast != null) {
12607 BroadcastRecord r = rl.curBroadcast;
12608 doNext = finishReceiverLocked(
12609 receiver.asBinder(), r.resultCode, r.resultData,
12610 r.resultExtras, r.resultAbort, true);
12611 }
12612
12613 if (rl.app != null) {
12614 rl.app.receivers.remove(rl);
12615 }
12616 removeReceiverLocked(rl);
12617 if (rl.linkedToDeath) {
12618 rl.linkedToDeath = false;
12619 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12620 }
12621 }
12622 }
12623
12624 if (!doNext) {
12625 return;
12626 }
12627
12628 final long origId = Binder.clearCallingIdentity();
12629 processNextBroadcast(false);
12630 trimApplications();
12631 Binder.restoreCallingIdentity(origId);
12632 }
12633
12634 void removeReceiverLocked(ReceiverList rl) {
12635 mRegisteredReceivers.remove(rl.receiver.asBinder());
12636 int N = rl.size();
12637 for (int i=0; i<N; i++) {
12638 mReceiverResolver.removeFilter(rl.get(i));
12639 }
12640 }
12641
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012642 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12643 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12644 ProcessRecord r = mLruProcesses.get(i);
12645 if (r.thread != null) {
12646 try {
12647 r.thread.dispatchPackageBroadcast(cmd, packages);
12648 } catch (RemoteException ex) {
12649 }
12650 }
12651 }
12652 }
12653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012654 private final int broadcastIntentLocked(ProcessRecord callerApp,
12655 String callerPackage, Intent intent, String resolvedType,
12656 IIntentReceiver resultTo, int resultCode, String resultData,
12657 Bundle map, String requiredPermission,
12658 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12659 intent = new Intent(intent);
12660
Joe Onorato8a9b2202010-02-26 18:56:32 -080012661 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012662 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12663 + " ordered=" + ordered);
12664 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012665 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012666 }
12667
12668 // Handle special intents: if this broadcast is from the package
12669 // manager about a package being removed, we need to remove all of
12670 // its activities from the history stack.
12671 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12672 intent.getAction());
12673 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12674 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012675 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012676 || uidRemoved) {
12677 if (checkComponentPermission(
12678 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12679 callingPid, callingUid, -1)
12680 == PackageManager.PERMISSION_GRANTED) {
12681 if (uidRemoved) {
12682 final Bundle intentExtras = intent.getExtras();
12683 final int uid = intentExtras != null
12684 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12685 if (uid >= 0) {
12686 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12687 synchronized (bs) {
12688 bs.removeUidStatsLocked(uid);
12689 }
12690 }
12691 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012692 // If resources are unvailble just force stop all
12693 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012694 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012695 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12696 if (list != null && (list.length > 0)) {
12697 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012698 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012699 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012700 sendPackageBroadcastLocked(
12701 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012702 }
12703 } else {
12704 Uri data = intent.getData();
12705 String ssp;
12706 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12707 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12708 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012709 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012710 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012711 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
12712 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12713 new String[] {ssp});
12714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012715 }
12716 }
12717 }
12718 } else {
12719 String msg = "Permission Denial: " + intent.getAction()
12720 + " broadcast from " + callerPackage + " (pid=" + callingPid
12721 + ", uid=" + callingUid + ")"
12722 + " requires "
12723 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012724 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012725 throw new SecurityException(msg);
12726 }
12727 }
12728
12729 /*
12730 * If this is the time zone changed action, queue up a message that will reset the timezone
12731 * of all currently running processes. This message will get queued up before the broadcast
12732 * happens.
12733 */
12734 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12735 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12736 }
12737
Dianne Hackborn854060af2009-07-09 18:14:31 -070012738 /*
12739 * Prevent non-system code (defined here to be non-persistent
12740 * processes) from sending protected broadcasts.
12741 */
12742 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12743 || callingUid == Process.SHELL_UID || callingUid == 0) {
12744 // Always okay.
12745 } else if (callerApp == null || !callerApp.persistent) {
12746 try {
12747 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12748 intent.getAction())) {
12749 String msg = "Permission Denial: not allowed to send broadcast "
12750 + intent.getAction() + " from pid="
12751 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012752 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012753 throw new SecurityException(msg);
12754 }
12755 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012756 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012757 return BROADCAST_SUCCESS;
12758 }
12759 }
12760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012761 // Add to the sticky list if requested.
12762 if (sticky) {
12763 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12764 callingPid, callingUid)
12765 != PackageManager.PERMISSION_GRANTED) {
12766 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12767 + callingPid + ", uid=" + callingUid
12768 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012769 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012770 throw new SecurityException(msg);
12771 }
12772 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012773 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012774 + " and enforce permission " + requiredPermission);
12775 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12776 }
12777 if (intent.getComponent() != null) {
12778 throw new SecurityException(
12779 "Sticky broadcasts can't target a specific component");
12780 }
12781 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12782 if (list == null) {
12783 list = new ArrayList<Intent>();
12784 mStickyBroadcasts.put(intent.getAction(), list);
12785 }
12786 int N = list.size();
12787 int i;
12788 for (i=0; i<N; i++) {
12789 if (intent.filterEquals(list.get(i))) {
12790 // This sticky already exists, replace it.
12791 list.set(i, new Intent(intent));
12792 break;
12793 }
12794 }
12795 if (i >= N) {
12796 list.add(new Intent(intent));
12797 }
12798 }
12799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012800 // Figure out who all will receive this broadcast.
12801 List receivers = null;
12802 List<BroadcastFilter> registeredReceivers = null;
12803 try {
12804 if (intent.getComponent() != null) {
12805 // Broadcast is going to one specific receiver class...
12806 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012807 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012808 if (ai != null) {
12809 receivers = new ArrayList();
12810 ResolveInfo ri = new ResolveInfo();
12811 ri.activityInfo = ai;
12812 receivers.add(ri);
12813 }
12814 } else {
12815 // Need to resolve the intent to interested receivers...
12816 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12817 == 0) {
12818 receivers =
12819 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012820 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012821 }
Mihai Preda074edef2009-05-18 17:13:31 +020012822 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012823 }
12824 } catch (RemoteException ex) {
12825 // pm is in same process, this will never happen.
12826 }
12827
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012828 final boolean replacePending =
12829 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12830
Joe Onorato8a9b2202010-02-26 18:56:32 -080012831 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012832 + " replacePending=" + replacePending);
12833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012834 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12835 if (!ordered && NR > 0) {
12836 // If we are not serializing this broadcast, then send the
12837 // registered receivers separately so they don't wait for the
12838 // components to be launched.
12839 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12840 callerPackage, callingPid, callingUid, requiredPermission,
12841 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012842 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012843 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012844 TAG, "Enqueueing parallel broadcast " + r
12845 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012846 boolean replaced = false;
12847 if (replacePending) {
12848 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12849 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012850 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012851 "***** DROPPING PARALLEL: " + intent);
12852 mParallelBroadcasts.set(i, r);
12853 replaced = true;
12854 break;
12855 }
12856 }
12857 }
12858 if (!replaced) {
12859 mParallelBroadcasts.add(r);
12860 scheduleBroadcastsLocked();
12861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012862 registeredReceivers = null;
12863 NR = 0;
12864 }
12865
12866 // Merge into one list.
12867 int ir = 0;
12868 if (receivers != null) {
12869 // A special case for PACKAGE_ADDED: do not allow the package
12870 // being added to see this broadcast. This prevents them from
12871 // using this as a back door to get run as soon as they are
12872 // installed. Maybe in the future we want to have a special install
12873 // broadcast or such for apps, but we'd like to deliberately make
12874 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012875 String skipPackages[] = null;
12876 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12877 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12878 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12879 Uri data = intent.getData();
12880 if (data != null) {
12881 String pkgName = data.getSchemeSpecificPart();
12882 if (pkgName != null) {
12883 skipPackages = new String[] { pkgName };
12884 }
12885 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012886 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012887 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012888 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012889 if (skipPackages != null && (skipPackages.length > 0)) {
12890 for (String skipPackage : skipPackages) {
12891 if (skipPackage != null) {
12892 int NT = receivers.size();
12893 for (int it=0; it<NT; it++) {
12894 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12895 if (curt.activityInfo.packageName.equals(skipPackage)) {
12896 receivers.remove(it);
12897 it--;
12898 NT--;
12899 }
12900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012901 }
12902 }
12903 }
12904
12905 int NT = receivers != null ? receivers.size() : 0;
12906 int it = 0;
12907 ResolveInfo curt = null;
12908 BroadcastFilter curr = null;
12909 while (it < NT && ir < NR) {
12910 if (curt == null) {
12911 curt = (ResolveInfo)receivers.get(it);
12912 }
12913 if (curr == null) {
12914 curr = registeredReceivers.get(ir);
12915 }
12916 if (curr.getPriority() >= curt.priority) {
12917 // Insert this broadcast record into the final list.
12918 receivers.add(it, curr);
12919 ir++;
12920 curr = null;
12921 it++;
12922 NT++;
12923 } else {
12924 // Skip to the next ResolveInfo in the final list.
12925 it++;
12926 curt = null;
12927 }
12928 }
12929 }
12930 while (ir < NR) {
12931 if (receivers == null) {
12932 receivers = new ArrayList();
12933 }
12934 receivers.add(registeredReceivers.get(ir));
12935 ir++;
12936 }
12937
12938 if ((receivers != null && receivers.size() > 0)
12939 || resultTo != null) {
12940 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12941 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012942 receivers, resultTo, resultCode, resultData, map, ordered,
12943 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012944 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012945 TAG, "Enqueueing ordered broadcast " + r
12946 + ": prev had " + mOrderedBroadcasts.size());
12947 if (DEBUG_BROADCAST) {
12948 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012949 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012950 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012951 boolean replaced = false;
12952 if (replacePending) {
12953 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12954 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012955 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012956 "***** DROPPING ORDERED: " + intent);
12957 mOrderedBroadcasts.set(i, r);
12958 replaced = true;
12959 break;
12960 }
12961 }
12962 }
12963 if (!replaced) {
12964 mOrderedBroadcasts.add(r);
12965 scheduleBroadcastsLocked();
12966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012967 }
12968
12969 return BROADCAST_SUCCESS;
12970 }
12971
12972 public final int broadcastIntent(IApplicationThread caller,
12973 Intent intent, String resolvedType, IIntentReceiver resultTo,
12974 int resultCode, String resultData, Bundle map,
12975 String requiredPermission, boolean serialized, boolean sticky) {
12976 // Refuse possible leaked file descriptors
12977 if (intent != null && intent.hasFileDescriptors() == true) {
12978 throw new IllegalArgumentException("File descriptors passed in Intent");
12979 }
12980
12981 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012982 int flags = intent.getFlags();
12983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012984 if (!mSystemReady) {
12985 // if the caller really truly claims to know what they're doing, go
12986 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012987 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12988 intent = new Intent(intent);
12989 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12990 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012991 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012992 + " before boot completion");
12993 throw new IllegalStateException("Cannot broadcast before boot completed");
12994 }
12995 }
12996
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012997 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12998 throw new IllegalArgumentException(
12999 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
13000 }
13001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013002 final ProcessRecord callerApp = getRecordForAppLocked(caller);
13003 final int callingPid = Binder.getCallingPid();
13004 final int callingUid = Binder.getCallingUid();
13005 final long origId = Binder.clearCallingIdentity();
13006 int res = broadcastIntentLocked(callerApp,
13007 callerApp != null ? callerApp.info.packageName : null,
13008 intent, resolvedType, resultTo,
13009 resultCode, resultData, map, requiredPermission, serialized,
13010 sticky, callingPid, callingUid);
13011 Binder.restoreCallingIdentity(origId);
13012 return res;
13013 }
13014 }
13015
13016 int broadcastIntentInPackage(String packageName, int uid,
13017 Intent intent, String resolvedType, IIntentReceiver resultTo,
13018 int resultCode, String resultData, Bundle map,
13019 String requiredPermission, boolean serialized, boolean sticky) {
13020 synchronized(this) {
13021 final long origId = Binder.clearCallingIdentity();
13022 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
13023 resultTo, resultCode, resultData, map, requiredPermission,
13024 serialized, sticky, -1, uid);
13025 Binder.restoreCallingIdentity(origId);
13026 return res;
13027 }
13028 }
13029
13030 public final void unbroadcastIntent(IApplicationThread caller,
13031 Intent intent) {
13032 // Refuse possible leaked file descriptors
13033 if (intent != null && intent.hasFileDescriptors() == true) {
13034 throw new IllegalArgumentException("File descriptors passed in Intent");
13035 }
13036
13037 synchronized(this) {
13038 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
13039 != PackageManager.PERMISSION_GRANTED) {
13040 String msg = "Permission Denial: unbroadcastIntent() from pid="
13041 + Binder.getCallingPid()
13042 + ", uid=" + Binder.getCallingUid()
13043 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013044 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013045 throw new SecurityException(msg);
13046 }
13047 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
13048 if (list != null) {
13049 int N = list.size();
13050 int i;
13051 for (i=0; i<N; i++) {
13052 if (intent.filterEquals(list.get(i))) {
13053 list.remove(i);
13054 break;
13055 }
13056 }
13057 }
13058 }
13059 }
13060
13061 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
13062 String resultData, Bundle resultExtras, boolean resultAbort,
13063 boolean explicit) {
13064 if (mOrderedBroadcasts.size() == 0) {
13065 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013066 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013067 }
13068 return false;
13069 }
13070 BroadcastRecord r = mOrderedBroadcasts.get(0);
13071 if (r.receiver == null) {
13072 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013073 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013074 }
13075 return false;
13076 }
13077 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013078 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013079 return false;
13080 }
13081 int state = r.state;
13082 r.state = r.IDLE;
13083 if (state == r.IDLE) {
13084 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013085 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013086 }
13087 }
13088 r.receiver = null;
13089 r.intent.setComponent(null);
13090 if (r.curApp != null) {
13091 r.curApp.curReceiver = null;
13092 }
13093 if (r.curFilter != null) {
13094 r.curFilter.receiverList.curBroadcast = null;
13095 }
13096 r.curFilter = null;
13097 r.curApp = null;
13098 r.curComponent = null;
13099 r.curReceiver = null;
13100 mPendingBroadcast = null;
13101
13102 r.resultCode = resultCode;
13103 r.resultData = resultData;
13104 r.resultExtras = resultExtras;
13105 r.resultAbort = resultAbort;
13106
13107 // We will process the next receiver right now if this is finishing
13108 // an app receiver (which is always asynchronous) or after we have
13109 // come back from calling a receiver.
13110 return state == BroadcastRecord.APP_RECEIVE
13111 || state == BroadcastRecord.CALL_DONE_RECEIVE;
13112 }
13113
13114 public void finishReceiver(IBinder who, int resultCode, String resultData,
13115 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013116 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013117
13118 // Refuse possible leaked file descriptors
13119 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
13120 throw new IllegalArgumentException("File descriptors passed in Bundle");
13121 }
13122
13123 boolean doNext;
13124
13125 final long origId = Binder.clearCallingIdentity();
13126
13127 synchronized(this) {
13128 doNext = finishReceiverLocked(
13129 who, resultCode, resultData, resultExtras, resultAbort, true);
13130 }
13131
13132 if (doNext) {
13133 processNextBroadcast(false);
13134 }
13135 trimApplications();
13136
13137 Binder.restoreCallingIdentity(origId);
13138 }
13139
13140 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
13141 if (r.nextReceiver > 0) {
13142 Object curReceiver = r.receivers.get(r.nextReceiver-1);
13143 if (curReceiver instanceof BroadcastFilter) {
13144 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080013145 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013146 System.identityHashCode(r),
13147 r.intent.getAction(),
13148 r.nextReceiver - 1,
13149 System.identityHashCode(bf));
13150 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080013151 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013152 System.identityHashCode(r),
13153 r.intent.getAction(),
13154 r.nextReceiver - 1,
13155 ((ResolveInfo)curReceiver).toString());
13156 }
13157 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013158 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013159 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013160 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013161 System.identityHashCode(r),
13162 r.intent.getAction(),
13163 r.nextReceiver,
13164 "NONE");
13165 }
13166 }
13167
13168 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013169 ProcessRecord app = null;
13170 String anrMessage = null;
13171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013172 synchronized (this) {
13173 if (mOrderedBroadcasts.size() == 0) {
13174 return;
13175 }
13176 long now = SystemClock.uptimeMillis();
13177 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013178 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013179 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013180 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013181 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013182 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013183 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013184 return;
13185 }
13186
Joe Onorato8a9b2202010-02-26 18:56:32 -080013187 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013188 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013189 r.anrCount++;
13190
13191 // Current receiver has passed its expiration date.
13192 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013193 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013194 return;
13195 }
13196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013197 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013198 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013199 logBroadcastReceiverDiscard(r);
13200 if (curReceiver instanceof BroadcastFilter) {
13201 BroadcastFilter bf = (BroadcastFilter)curReceiver;
13202 if (bf.receiverList.pid != 0
13203 && bf.receiverList.pid != MY_PID) {
13204 synchronized (this.mPidsSelfLocked) {
13205 app = this.mPidsSelfLocked.get(
13206 bf.receiverList.pid);
13207 }
13208 }
13209 } else {
13210 app = r.curApp;
13211 }
13212
13213 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013214 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013215 }
13216
13217 if (mPendingBroadcast == r) {
13218 mPendingBroadcast = null;
13219 }
13220
13221 // Move on to the next receiver.
13222 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13223 r.resultExtras, r.resultAbort, true);
13224 scheduleBroadcastsLocked();
13225 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013226
13227 if (anrMessage != null) {
13228 appNotResponding(app, null, null, anrMessage);
13229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013230 }
13231
13232 private final void processCurBroadcastLocked(BroadcastRecord r,
13233 ProcessRecord app) throws RemoteException {
13234 if (app.thread == null) {
13235 throw new RemoteException();
13236 }
13237 r.receiver = app.thread.asBinder();
13238 r.curApp = app;
13239 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013240 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013241
13242 // Tell the application to launch this receiver.
13243 r.intent.setComponent(r.curComponent);
13244
13245 boolean started = false;
13246 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013247 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013248 "Delivering to component " + r.curComponent
13249 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070013250 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013251 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
13252 r.resultCode, r.resultData, r.resultExtras, r.ordered);
13253 started = true;
13254 } finally {
13255 if (!started) {
13256 r.receiver = null;
13257 r.curApp = null;
13258 app.curReceiver = null;
13259 }
13260 }
13261
13262 }
13263
13264 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013265 Intent intent, int resultCode, String data, Bundle extras,
13266 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013267 if (app != null && app.thread != null) {
13268 // If we have an app thread, do the call through that so it is
13269 // correctly ordered with other one-way calls.
13270 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013271 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013272 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013273 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013274 }
13275 }
13276
13277 private final void deliverToRegisteredReceiver(BroadcastRecord r,
13278 BroadcastFilter filter, boolean ordered) {
13279 boolean skip = false;
13280 if (filter.requiredPermission != null) {
13281 int perm = checkComponentPermission(filter.requiredPermission,
13282 r.callingPid, r.callingUid, -1);
13283 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013284 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013285 + r.intent.toString()
13286 + " from " + r.callerPackage + " (pid="
13287 + r.callingPid + ", uid=" + r.callingUid + ")"
13288 + " requires " + filter.requiredPermission
13289 + " due to registered receiver " + filter);
13290 skip = true;
13291 }
13292 }
13293 if (r.requiredPermission != null) {
13294 int perm = checkComponentPermission(r.requiredPermission,
13295 filter.receiverList.pid, filter.receiverList.uid, -1);
13296 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013297 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013298 + r.intent.toString()
13299 + " to " + filter.receiverList.app
13300 + " (pid=" + filter.receiverList.pid
13301 + ", uid=" + filter.receiverList.uid + ")"
13302 + " requires " + r.requiredPermission
13303 + " due to sender " + r.callerPackage
13304 + " (uid " + r.callingUid + ")");
13305 skip = true;
13306 }
13307 }
13308
13309 if (!skip) {
13310 // If this is not being sent as an ordered broadcast, then we
13311 // don't want to touch the fields that keep track of the current
13312 // state of ordered broadcasts.
13313 if (ordered) {
13314 r.receiver = filter.receiverList.receiver.asBinder();
13315 r.curFilter = filter;
13316 filter.receiverList.curBroadcast = r;
13317 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013318 if (filter.receiverList.app != null) {
13319 // Bump hosting application to no longer be in background
13320 // scheduling class. Note that we can't do that if there
13321 // isn't an app... but we can only be in that case for
13322 // things that directly call the IActivityManager API, which
13323 // are already core system stuff so don't matter for this.
13324 r.curApp = filter.receiverList.app;
13325 filter.receiverList.app.curReceiver = r;
13326 updateOomAdjLocked();
13327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013328 }
13329 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013330 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013331 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013332 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013333 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013334 }
13335 performReceive(filter.receiverList.app, filter.receiverList.receiver,
13336 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013337 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013338 if (ordered) {
13339 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13340 }
13341 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013342 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013343 if (ordered) {
13344 r.receiver = null;
13345 r.curFilter = null;
13346 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013347 if (filter.receiverList.app != null) {
13348 filter.receiverList.app.curReceiver = null;
13349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013350 }
13351 }
13352 }
13353 }
13354
Dianne Hackborn12527f92009-11-11 17:39:50 -080013355 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13356 if (r.callingUid < 0) {
13357 // This was from a registerReceiver() call; ignore it.
13358 return;
13359 }
13360 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13361 MAX_BROADCAST_HISTORY-1);
13362 r.finishTime = SystemClock.uptimeMillis();
13363 mBroadcastHistory[0] = r;
13364 }
13365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013366 private final void processNextBroadcast(boolean fromMsg) {
13367 synchronized(this) {
13368 BroadcastRecord r;
13369
Joe Onorato8a9b2202010-02-26 18:56:32 -080013370 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013371 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013372 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013373
13374 updateCpuStats();
13375
13376 if (fromMsg) {
13377 mBroadcastsScheduled = false;
13378 }
13379
13380 // First, deliver any non-serialized broadcasts right away.
13381 while (mParallelBroadcasts.size() > 0) {
13382 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013383 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013384 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013385 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013386 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013387 for (int i=0; i<N; i++) {
13388 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013389 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013390 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013391 + target + ": " + r);
13392 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13393 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013394 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013395 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013396 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013397 }
13398
13399 // Now take care of the next serialized one...
13400
13401 // If we are waiting for a process to come up to handle the next
13402 // broadcast, then do nothing at this point. Just in case, we
13403 // check that the process we're waiting for still exists.
13404 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013405 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013406 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013407 + mPendingBroadcast.curApp);
13408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013409
13410 boolean isDead;
13411 synchronized (mPidsSelfLocked) {
13412 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13413 }
13414 if (!isDead) {
13415 // It's still alive, so keep waiting
13416 return;
13417 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013418 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013419 + " died before responding to broadcast");
13420 mPendingBroadcast = null;
13421 }
13422 }
13423
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013424 boolean looped = false;
13425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013426 do {
13427 if (mOrderedBroadcasts.size() == 0) {
13428 // No more broadcasts pending, so all done!
13429 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013430 if (looped) {
13431 // If we had finished the last ordered broadcast, then
13432 // make sure all processes have correct oom and sched
13433 // adjustments.
13434 updateOomAdjLocked();
13435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013436 return;
13437 }
13438 r = mOrderedBroadcasts.get(0);
13439 boolean forceReceive = false;
13440
13441 // Ensure that even if something goes awry with the timeout
13442 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013443 // and continue to make progress.
13444 //
13445 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
13446 // receivers don't get executed with with timeouts. They're intended for
13447 // one time heavy lifting after system upgrades and can take
13448 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013449 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013450 if (mSystemReady && r.dispatchTime > 0) {
13451 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013452 if ((numReceivers > 0) &&
13453 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013454 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013455 + " now=" + now
13456 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013457 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013458 + " intent=" + r.intent
13459 + " numReceivers=" + numReceivers
13460 + " nextReceiver=" + r.nextReceiver
13461 + " state=" + r.state);
13462 broadcastTimeout(); // forcibly finish this broadcast
13463 forceReceive = true;
13464 r.state = BroadcastRecord.IDLE;
13465 }
13466 }
13467
13468 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013469 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013470 "processNextBroadcast() called when not idle (state="
13471 + r.state + ")");
13472 return;
13473 }
13474
13475 if (r.receivers == null || r.nextReceiver >= numReceivers
13476 || r.resultAbort || forceReceive) {
13477 // No more receivers for this broadcast! Send the final
13478 // result if requested...
13479 if (r.resultTo != null) {
13480 try {
13481 if (DEBUG_BROADCAST) {
13482 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013483 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013484 + " seq=" + seq + " app=" + r.callerApp);
13485 }
13486 performReceive(r.callerApp, r.resultTo,
13487 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013488 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013489 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013490 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013491 }
13492 }
13493
Joe Onorato8a9b2202010-02-26 18:56:32 -080013494 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013495 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13496
Joe Onorato8a9b2202010-02-26 18:56:32 -080013497 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013498 + r);
13499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013500 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013501 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013502 mOrderedBroadcasts.remove(0);
13503 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013504 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013505 continue;
13506 }
13507 } while (r == null);
13508
13509 // Get the next receiver...
13510 int recIdx = r.nextReceiver++;
13511
13512 // Keep track of when this receiver started, and make sure there
13513 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013514 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013515 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013516 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013517
Joe Onorato8a9b2202010-02-26 18:56:32 -080013518 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013519 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013520 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013521 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013522 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013523 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013524 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013525 }
13526
13527 Object nextReceiver = r.receivers.get(recIdx);
13528 if (nextReceiver instanceof BroadcastFilter) {
13529 // Simple case: this is a registered receiver who gets
13530 // a direct call.
13531 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013532 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013533 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013534 + filter + ": " + r);
13535 deliverToRegisteredReceiver(r, filter, r.ordered);
13536 if (r.receiver == null || !r.ordered) {
13537 // The receiver has already finished, so schedule to
13538 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013539 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13540 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013541 r.state = BroadcastRecord.IDLE;
13542 scheduleBroadcastsLocked();
13543 }
13544 return;
13545 }
13546
13547 // Hard case: need to instantiate the receiver, possibly
13548 // starting its application process to host it.
13549
13550 ResolveInfo info =
13551 (ResolveInfo)nextReceiver;
13552
13553 boolean skip = false;
13554 int perm = checkComponentPermission(info.activityInfo.permission,
13555 r.callingPid, r.callingUid,
13556 info.activityInfo.exported
13557 ? -1 : info.activityInfo.applicationInfo.uid);
13558 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013559 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013560 + r.intent.toString()
13561 + " from " + r.callerPackage + " (pid=" + r.callingPid
13562 + ", uid=" + r.callingUid + ")"
13563 + " requires " + info.activityInfo.permission
13564 + " due to receiver " + info.activityInfo.packageName
13565 + "/" + info.activityInfo.name);
13566 skip = true;
13567 }
13568 if (r.callingUid != Process.SYSTEM_UID &&
13569 r.requiredPermission != null) {
13570 try {
13571 perm = ActivityThread.getPackageManager().
13572 checkPermission(r.requiredPermission,
13573 info.activityInfo.applicationInfo.packageName);
13574 } catch (RemoteException e) {
13575 perm = PackageManager.PERMISSION_DENIED;
13576 }
13577 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013578 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013579 + r.intent + " to "
13580 + info.activityInfo.applicationInfo.packageName
13581 + " requires " + r.requiredPermission
13582 + " due to sender " + r.callerPackage
13583 + " (uid " + r.callingUid + ")");
13584 skip = true;
13585 }
13586 }
13587 if (r.curApp != null && r.curApp.crashing) {
13588 // If the target process is crashing, just skip it.
13589 skip = true;
13590 }
13591
13592 if (skip) {
13593 r.receiver = null;
13594 r.curFilter = null;
13595 r.state = BroadcastRecord.IDLE;
13596 scheduleBroadcastsLocked();
13597 return;
13598 }
13599
13600 r.state = BroadcastRecord.APP_RECEIVE;
13601 String targetProcess = info.activityInfo.processName;
13602 r.curComponent = new ComponentName(
13603 info.activityInfo.applicationInfo.packageName,
13604 info.activityInfo.name);
13605 r.curReceiver = info.activityInfo;
13606
13607 // Is this receiver's application already running?
13608 ProcessRecord app = getProcessRecordLocked(targetProcess,
13609 info.activityInfo.applicationInfo.uid);
13610 if (app != null && app.thread != null) {
13611 try {
13612 processCurBroadcastLocked(r, app);
13613 return;
13614 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013615 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013616 + r.curComponent, e);
13617 }
13618
13619 // If a dead object exception was thrown -- fall through to
13620 // restart the application.
13621 }
13622
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013623 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013624 if ((r.curApp=startProcessLocked(targetProcess,
13625 info.activityInfo.applicationInfo, true,
13626 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013627 "broadcast", r.curComponent,
13628 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13629 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013630 // Ah, this recipient is unavailable. Finish it if necessary,
13631 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013632 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013633 + info.activityInfo.applicationInfo.packageName + "/"
13634 + info.activityInfo.applicationInfo.uid + " for broadcast "
13635 + r.intent + ": process is bad");
13636 logBroadcastReceiverDiscard(r);
13637 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13638 r.resultExtras, r.resultAbort, true);
13639 scheduleBroadcastsLocked();
13640 r.state = BroadcastRecord.IDLE;
13641 return;
13642 }
13643
13644 mPendingBroadcast = r;
13645 }
13646 }
13647
13648 // =========================================================
13649 // INSTRUMENTATION
13650 // =========================================================
13651
13652 public boolean startInstrumentation(ComponentName className,
13653 String profileFile, int flags, Bundle arguments,
13654 IInstrumentationWatcher watcher) {
13655 // Refuse possible leaked file descriptors
13656 if (arguments != null && arguments.hasFileDescriptors()) {
13657 throw new IllegalArgumentException("File descriptors passed in Bundle");
13658 }
13659
13660 synchronized(this) {
13661 InstrumentationInfo ii = null;
13662 ApplicationInfo ai = null;
13663 try {
13664 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013665 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013666 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013667 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013668 } catch (PackageManager.NameNotFoundException e) {
13669 }
13670 if (ii == null) {
13671 reportStartInstrumentationFailure(watcher, className,
13672 "Unable to find instrumentation info for: " + className);
13673 return false;
13674 }
13675 if (ai == null) {
13676 reportStartInstrumentationFailure(watcher, className,
13677 "Unable to find instrumentation target package: " + ii.targetPackage);
13678 return false;
13679 }
13680
13681 int match = mContext.getPackageManager().checkSignatures(
13682 ii.targetPackage, ii.packageName);
13683 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13684 String msg = "Permission Denial: starting instrumentation "
13685 + className + " from pid="
13686 + Binder.getCallingPid()
13687 + ", uid=" + Binder.getCallingPid()
13688 + " not allowed because package " + ii.packageName
13689 + " does not have a signature matching the target "
13690 + ii.targetPackage;
13691 reportStartInstrumentationFailure(watcher, className, msg);
13692 throw new SecurityException(msg);
13693 }
13694
13695 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013696 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013697 ProcessRecord app = addAppLocked(ai);
13698 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013699 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013700 app.instrumentationProfileFile = profileFile;
13701 app.instrumentationArguments = arguments;
13702 app.instrumentationWatcher = watcher;
13703 app.instrumentationResultClass = className;
13704 Binder.restoreCallingIdentity(origId);
13705 }
13706
13707 return true;
13708 }
13709
13710 /**
13711 * Report errors that occur while attempting to start Instrumentation. Always writes the
13712 * error to the logs, but if somebody is watching, send the report there too. This enables
13713 * the "am" command to report errors with more information.
13714 *
13715 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13716 * @param cn The component name of the instrumentation.
13717 * @param report The error report.
13718 */
13719 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13720 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013721 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013722 try {
13723 if (watcher != null) {
13724 Bundle results = new Bundle();
13725 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13726 results.putString("Error", report);
13727 watcher.instrumentationStatus(cn, -1, results);
13728 }
13729 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013730 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013731 }
13732 }
13733
13734 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13735 if (app.instrumentationWatcher != null) {
13736 try {
13737 // NOTE: IInstrumentationWatcher *must* be oneway here
13738 app.instrumentationWatcher.instrumentationFinished(
13739 app.instrumentationClass,
13740 resultCode,
13741 results);
13742 } catch (RemoteException e) {
13743 }
13744 }
13745 app.instrumentationWatcher = null;
13746 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013747 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013748 app.instrumentationProfileFile = null;
13749 app.instrumentationArguments = null;
13750
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013751 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013752 }
13753
13754 public void finishInstrumentation(IApplicationThread target,
13755 int resultCode, Bundle results) {
13756 // Refuse possible leaked file descriptors
13757 if (results != null && results.hasFileDescriptors()) {
13758 throw new IllegalArgumentException("File descriptors passed in Intent");
13759 }
13760
13761 synchronized(this) {
13762 ProcessRecord app = getRecordForAppLocked(target);
13763 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013764 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013765 return;
13766 }
13767 final long origId = Binder.clearCallingIdentity();
13768 finishInstrumentationLocked(app, resultCode, results);
13769 Binder.restoreCallingIdentity(origId);
13770 }
13771 }
13772
13773 // =========================================================
13774 // CONFIGURATION
13775 // =========================================================
13776
13777 public ConfigurationInfo getDeviceConfigurationInfo() {
13778 ConfigurationInfo config = new ConfigurationInfo();
13779 synchronized (this) {
13780 config.reqTouchScreen = mConfiguration.touchscreen;
13781 config.reqKeyboardType = mConfiguration.keyboard;
13782 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013783 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13784 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013785 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13786 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013787 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13788 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013789 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13790 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013791 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013792 }
13793 return config;
13794 }
13795
13796 public Configuration getConfiguration() {
13797 Configuration ci;
13798 synchronized(this) {
13799 ci = new Configuration(mConfiguration);
13800 }
13801 return ci;
13802 }
13803
13804 public void updateConfiguration(Configuration values) {
13805 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13806 "updateConfiguration()");
13807
13808 synchronized(this) {
13809 if (values == null && mWindowManager != null) {
13810 // sentinel: fetch the current configuration from the window manager
13811 values = mWindowManager.computeNewConfiguration();
13812 }
13813
13814 final long origId = Binder.clearCallingIdentity();
13815 updateConfigurationLocked(values, null);
13816 Binder.restoreCallingIdentity(origId);
13817 }
13818 }
13819
13820 /**
13821 * Do either or both things: (1) change the current configuration, and (2)
13822 * make sure the given activity is running with the (now) current
13823 * configuration. Returns true if the activity has been left running, or
13824 * false if <var>starting</var> is being destroyed to match the new
13825 * configuration.
13826 */
13827 public boolean updateConfigurationLocked(Configuration values,
13828 HistoryRecord starting) {
13829 int changes = 0;
13830
13831 boolean kept = true;
13832
13833 if (values != null) {
13834 Configuration newConfig = new Configuration(mConfiguration);
13835 changes = newConfig.updateFrom(values);
13836 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013837 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013838 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013839 }
13840
Doug Zongker2bec3d42009-12-04 12:52:44 -080013841 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013842
13843 if (values.locale != null) {
13844 saveLocaleLocked(values.locale,
13845 !values.locale.equals(mConfiguration.locale),
13846 values.userSetLocale);
13847 }
13848
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013849 mConfigurationSeq++;
13850 if (mConfigurationSeq <= 0) {
13851 mConfigurationSeq = 1;
13852 }
13853 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013854 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013855 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013856
13857 AttributeCache ac = AttributeCache.instance();
13858 if (ac != null) {
13859 ac.updateConfiguration(mConfiguration);
13860 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013861
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013862 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13863 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13864 msg.obj = new Configuration(mConfiguration);
13865 mHandler.sendMessage(msg);
13866 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013867
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013868 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13869 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013870 try {
13871 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013872 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013873 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013874 app.thread.scheduleConfigurationChanged(mConfiguration);
13875 }
13876 } catch (Exception e) {
13877 }
13878 }
13879 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013880 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13881 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013882 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13883 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013884 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13885 broadcastIntentLocked(null, null,
13886 new Intent(Intent.ACTION_LOCALE_CHANGED),
13887 null, null, 0, null, null,
13888 null, false, false, MY_PID, Process.SYSTEM_UID);
13889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013890 }
13891 }
13892
13893 if (changes != 0 && starting == null) {
13894 // If the configuration changed, and the caller is not already
13895 // in the process of starting an activity, then find the top
13896 // activity to check if its configuration needs to change.
13897 starting = topRunningActivityLocked(null);
13898 }
13899
13900 if (starting != null) {
13901 kept = ensureActivityConfigurationLocked(starting, changes);
13902 if (kept) {
13903 // If this didn't result in the starting activity being
13904 // destroyed, then we need to make sure at this point that all
13905 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013906 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013907 + ", ensuring others are correct.");
13908 ensureActivitiesVisibleLocked(starting, changes);
13909 }
13910 }
13911
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013912 if (values != null && mWindowManager != null) {
13913 mWindowManager.setNewConfiguration(mConfiguration);
13914 }
13915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013916 return kept;
13917 }
13918
13919 private final boolean relaunchActivityLocked(HistoryRecord r,
13920 int changes, boolean andResume) {
13921 List<ResultInfo> results = null;
13922 List<Intent> newIntents = null;
13923 if (andResume) {
13924 results = r.results;
13925 newIntents = r.newIntents;
13926 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013927 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013928 + " with results=" + results + " newIntents=" + newIntents
13929 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013930 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13931 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013932 r.task.taskId, r.shortComponentName);
13933
13934 r.startFreezingScreenLocked(r.app, 0);
13935
13936 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013937 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013938 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013939 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013940 // Note: don't need to call pauseIfSleepingLocked() here, because
13941 // the caller will only pass in 'andResume' if this activity is
13942 // currently resumed, which implies we aren't sleeping.
13943 } catch (RemoteException e) {
13944 return false;
13945 }
13946
13947 if (andResume) {
13948 r.results = null;
13949 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013950 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013951 }
13952
13953 return true;
13954 }
13955
13956 /**
13957 * Make sure the given activity matches the current configuration. Returns
13958 * false if the activity had to be destroyed. Returns true if the
13959 * configuration is the same, or the activity will remain running as-is
13960 * for whatever reason. Ensures the HistoryRecord is updated with the
13961 * correct configuration and all other bookkeeping is handled.
13962 */
13963 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13964 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070013965 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013966 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13967 "Skipping config check (will change): " + r);
13968 return true;
13969 }
13970
Joe Onorato8a9b2202010-02-26 18:56:32 -080013971 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013972 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013973
13974 // Short circuit: if the two configurations are the exact same
13975 // object (the common case), then there is nothing to do.
13976 Configuration newConfig = mConfiguration;
13977 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013978 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013979 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013980 return true;
13981 }
13982
13983 // We don't worry about activities that are finishing.
13984 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013985 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013986 "Configuration doesn't matter in finishing " + r);
13987 r.stopFreezingScreenLocked(false);
13988 return true;
13989 }
13990
13991 // Okay we now are going to make this activity have the new config.
13992 // But then we need to figure out how it needs to deal with that.
13993 Configuration oldConfig = r.configuration;
13994 r.configuration = newConfig;
13995
13996 // If the activity isn't currently running, just leave the new
13997 // configuration and it will pick that up next time it starts.
13998 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013999 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014000 "Configuration doesn't matter not running " + r);
14001 r.stopFreezingScreenLocked(false);
14002 return true;
14003 }
14004
14005 // If the activity isn't persistent, there is a chance we will
14006 // need to restart it.
14007 if (!r.persistent) {
14008
14009 // Figure out what has changed between the two configurations.
14010 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014011 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014012 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014013 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014014 + Integer.toHexString(r.info.configChanges)
14015 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014016 }
14017 if ((changes&(~r.info.configChanges)) != 0) {
14018 // Aha, the activity isn't handling the change, so DIE DIE DIE.
14019 r.configChangeFlags |= changes;
14020 r.startFreezingScreenLocked(r.app, globalChanges);
14021 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014022 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014023 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014024 destroyActivityLocked(r, true);
14025 } else if (r.state == ActivityState.PAUSING) {
14026 // A little annoying: we are waiting for this activity to
14027 // finish pausing. Let's not do anything now, but just
14028 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014029 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014030 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014031 r.configDestroy = true;
14032 return true;
14033 } else if (r.state == ActivityState.RESUMED) {
14034 // Try to optimize this case: the configuration is changing
14035 // and we need to restart the top, resumed activity.
14036 // Instead of doing the normal handshaking, just say
14037 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080014038 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014039 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014040 relaunchActivityLocked(r, r.configChangeFlags, true);
14041 r.configChangeFlags = 0;
14042 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014043 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014044 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014045 relaunchActivityLocked(r, r.configChangeFlags, false);
14046 r.configChangeFlags = 0;
14047 }
14048
14049 // All done... tell the caller we weren't able to keep this
14050 // activity around.
14051 return false;
14052 }
14053 }
14054
14055 // Default case: the activity can handle this new configuration, so
14056 // hand it over. Note that we don't need to give it the new
14057 // configuration, since we always send configuration changes to all
14058 // process when they happen so it can just use whatever configuration
14059 // it last got.
14060 if (r.app != null && r.app.thread != null) {
14061 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014062 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014063 r.app.thread.scheduleActivityConfigurationChanged(r);
14064 } catch (RemoteException e) {
14065 // If process died, whatever.
14066 }
14067 }
14068 r.stopFreezingScreenLocked(false);
14069
14070 return true;
14071 }
14072
14073 /**
14074 * Save the locale. You must be inside a synchronized (this) block.
14075 */
14076 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
14077 if(isDiff) {
14078 SystemProperties.set("user.language", l.getLanguage());
14079 SystemProperties.set("user.region", l.getCountry());
14080 }
14081
14082 if(isPersist) {
14083 SystemProperties.set("persist.sys.language", l.getLanguage());
14084 SystemProperties.set("persist.sys.country", l.getCountry());
14085 SystemProperties.set("persist.sys.localevar", l.getVariant());
14086 }
14087 }
14088
14089 // =========================================================
14090 // LIFETIME MANAGEMENT
14091 // =========================================================
14092
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014093 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
14094 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014095 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014096 // This adjustment has already been computed. If we are calling
14097 // from the top, we may have already computed our adjustment with
14098 // an earlier hidden adjustment that isn't really for us... if
14099 // so, use the new hidden adjustment.
14100 if (!recursed && app.hidden) {
14101 app.curAdj = hiddenAdj;
14102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014103 return app.curAdj;
14104 }
14105
14106 if (app.thread == null) {
14107 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014108 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014109 return (app.curAdj=EMPTY_APP_ADJ);
14110 }
14111
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014112 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
14113 // The max adjustment doesn't allow this app to be anything
14114 // below foreground, so it is not worth doing work for it.
14115 app.adjType = "fixed";
14116 app.adjSeq = mAdjSeq;
14117 app.curRawAdj = app.maxAdj;
14118 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
14119 return (app.curAdj=app.maxAdj);
14120 }
14121
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014122 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014123 app.adjSource = null;
14124 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014125 app.empty = false;
14126 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014127
The Android Open Source Project4df24232009-03-05 14:34:35 -080014128 // Determine the importance of the process, starting with most
14129 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014130 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014131 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014132 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014133 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014134 // The last app on the list is the foreground app.
14135 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014136 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014137 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014138 } else if (app.instrumentationClass != null) {
14139 // Don't want to kill running instrumentation.
14140 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014141 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014142 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014143 } else if (app.persistentActivities > 0) {
14144 // Special persistent activities... shouldn't be used these days.
14145 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014146 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014147 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014148 } else if (app.curReceiver != null ||
14149 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
14150 // An app that is currently receiving a broadcast also
14151 // counts as being in the foreground.
14152 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014153 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014154 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014155 } else if (app.executingServices.size() > 0) {
14156 // An app that is currently executing a service callback also
14157 // counts as being in the foreground.
14158 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014159 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014160 app.adjType = "exec-service";
14161 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014162 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014163 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014164 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014165 app.adjType = "foreground-service";
14166 } else if (app.forcingToForeground != null) {
14167 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014168 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014169 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014170 app.adjType = "force-foreground";
14171 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014172 } else if (app == mHeavyWeightProcess) {
14173 // We don't want to kill the current heavy-weight process.
14174 adj = HEAVY_WEIGHT_APP_ADJ;
14175 schedGroup = Process.THREAD_GROUP_DEFAULT;
14176 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080014177 } else if (app == mHomeProcess) {
14178 // This process is hosting what we currently consider to be the
14179 // home app, so we don't want to let it go into the background.
14180 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014181 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014182 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014183 } else if ((N=app.activities.size()) != 0) {
14184 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014185 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014186 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014187 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014188 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014189 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014190 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014191 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014192 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014193 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014194 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014195 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014196 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014197 break;
14198 }
14199 }
14200 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014201 // A very not-needed process. If this is lower in the lru list,
14202 // we will push it in to the empty bucket.
14203 app.hidden = true;
14204 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014205 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014206 adj = hiddenAdj;
14207 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014208 }
14209
Joe Onorato8a9b2202010-02-26 18:56:32 -080014210 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014211
The Android Open Source Project4df24232009-03-05 14:34:35 -080014212 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014213 // there are applications dependent on our services or providers, but
14214 // this gives us a baseline and makes sure we don't get into an
14215 // infinite recursion.
14216 app.adjSeq = mAdjSeq;
14217 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014218
Christopher Tate6fa95972009-06-05 18:43:55 -070014219 if (mBackupTarget != null && app == mBackupTarget.app) {
14220 // If possible we want to avoid killing apps while they're being backed up
14221 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014222 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070014223 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014224 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014225 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070014226 }
14227 }
14228
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014229 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
14230 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014231 final long now = SystemClock.uptimeMillis();
14232 // This process is more important if the top activity is
14233 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070014234 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014235 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014236 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014237 if (s.startRequested) {
14238 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14239 // This service has seen some activity within
14240 // recent memory, so we will keep its process ahead
14241 // of the background processes.
14242 if (adj > SECONDARY_SERVER_ADJ) {
14243 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014244 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014245 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014246 }
14247 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014248 // If we have let the service slide into the background
14249 // state, still have some text describing what it is doing
14250 // even though the service no longer has an impact.
14251 if (adj > SECONDARY_SERVER_ADJ) {
14252 app.adjType = "started-bg-services";
14253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014254 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014255 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
14256 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014257 Iterator<ConnectionRecord> kt
14258 = s.connections.values().iterator();
14259 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14260 // XXX should compute this based on the max of
14261 // all connected clients.
14262 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014263 if (cr.binding.client == app) {
14264 // Binding to ourself is not interesting.
14265 continue;
14266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014267 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
14268 ProcessRecord client = cr.binding.client;
14269 int myHiddenAdj = hiddenAdj;
14270 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014271 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014272 myHiddenAdj = client.hiddenAdj;
14273 } else {
14274 myHiddenAdj = VISIBLE_APP_ADJ;
14275 }
14276 }
14277 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014278 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014279 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014280 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014281 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014282 if (!client.hidden) {
14283 app.hidden = false;
14284 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014285 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014286 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14287 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014288 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014289 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014290 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014291 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14292 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14293 schedGroup = Process.THREAD_GROUP_DEFAULT;
14294 }
14295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014296 }
14297 HistoryRecord a = cr.activity;
14298 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014299 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014300 //}
14301 if (a != null && adj > FOREGROUND_APP_ADJ &&
14302 (a.state == ActivityState.RESUMED
14303 || a.state == ActivityState.PAUSING)) {
14304 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014305 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014306 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014307 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014308 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14309 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014310 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014311 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014312 }
14313 }
14314 }
14315 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014316
14317 // Finally, f this process has active services running in it, we
14318 // would like to avoid killing it unless it would prevent the current
14319 // application from running. By default we put the process in
14320 // with the rest of the background processes; as we scan through
14321 // its services we may bump it up from there.
14322 if (adj > hiddenAdj) {
14323 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014324 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014325 app.adjType = "bg-services";
14326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014327 }
14328
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014329 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
14330 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014331 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014332 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
14333 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014334 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014335 if (cpr.clients.size() != 0) {
14336 Iterator<ProcessRecord> kt = cpr.clients.iterator();
14337 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14338 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014339 if (client == app) {
14340 // Being our own client is not interesting.
14341 continue;
14342 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014343 int myHiddenAdj = hiddenAdj;
14344 if (myHiddenAdj > client.hiddenAdj) {
14345 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
14346 myHiddenAdj = client.hiddenAdj;
14347 } else {
14348 myHiddenAdj = FOREGROUND_APP_ADJ;
14349 }
14350 }
14351 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014352 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014353 if (adj > clientAdj) {
14354 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014355 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014356 if (!client.hidden) {
14357 app.hidden = false;
14358 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014359 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014360 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14361 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014362 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014363 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014364 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014365 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14366 schedGroup = Process.THREAD_GROUP_DEFAULT;
14367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014368 }
14369 }
14370 // If the provider has external (non-framework) process
14371 // dependencies, ensure that its adjustment is at least
14372 // FOREGROUND_APP_ADJ.
14373 if (cpr.externals != 0) {
14374 if (adj > FOREGROUND_APP_ADJ) {
14375 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014376 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014377 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014378 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014379 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014380 }
14381 }
14382 }
14383 }
14384
14385 app.curRawAdj = adj;
14386
Joe Onorato8a9b2202010-02-26 18:56:32 -080014387 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014388 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14389 if (adj > app.maxAdj) {
14390 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014391 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014392 schedGroup = Process.THREAD_GROUP_DEFAULT;
14393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014394 }
14395
14396 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014397 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014399 return adj;
14400 }
14401
14402 /**
14403 * Ask a given process to GC right now.
14404 */
14405 final void performAppGcLocked(ProcessRecord app) {
14406 try {
14407 app.lastRequestedGc = SystemClock.uptimeMillis();
14408 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014409 if (app.reportLowMemory) {
14410 app.reportLowMemory = false;
14411 app.thread.scheduleLowMemory();
14412 } else {
14413 app.thread.processInBackground();
14414 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014415 }
14416 } catch (Exception e) {
14417 // whatever.
14418 }
14419 }
14420
14421 /**
14422 * Returns true if things are idle enough to perform GCs.
14423 */
Josh Bartel7f208742010-02-25 11:01:44 -060014424 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014425 return mParallelBroadcasts.size() == 0
14426 && mOrderedBroadcasts.size() == 0
14427 && (mSleeping || (mResumedActivity != null &&
14428 mResumedActivity.idle));
14429 }
14430
14431 /**
14432 * Perform GCs on all processes that are waiting for it, but only
14433 * if things are idle.
14434 */
14435 final void performAppGcsLocked() {
14436 final int N = mProcessesToGc.size();
14437 if (N <= 0) {
14438 return;
14439 }
Josh Bartel7f208742010-02-25 11:01:44 -060014440 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014441 while (mProcessesToGc.size() > 0) {
14442 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014443 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014444 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14445 <= SystemClock.uptimeMillis()) {
14446 // To avoid spamming the system, we will GC processes one
14447 // at a time, waiting a few seconds between each.
14448 performAppGcLocked(proc);
14449 scheduleAppGcsLocked();
14450 return;
14451 } else {
14452 // It hasn't been long enough since we last GCed this
14453 // process... put it in the list to wait for its time.
14454 addProcessToGcListLocked(proc);
14455 break;
14456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014457 }
14458 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014459
14460 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014461 }
14462 }
14463
14464 /**
14465 * If all looks good, perform GCs on all processes waiting for them.
14466 */
14467 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014468 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014469 performAppGcsLocked();
14470 return;
14471 }
14472 // Still not idle, wait some more.
14473 scheduleAppGcsLocked();
14474 }
14475
14476 /**
14477 * Schedule the execution of all pending app GCs.
14478 */
14479 final void scheduleAppGcsLocked() {
14480 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014481
14482 if (mProcessesToGc.size() > 0) {
14483 // Schedule a GC for the time to the next process.
14484 ProcessRecord proc = mProcessesToGc.get(0);
14485 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14486
14487 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14488 long now = SystemClock.uptimeMillis();
14489 if (when < (now+GC_TIMEOUT)) {
14490 when = now + GC_TIMEOUT;
14491 }
14492 mHandler.sendMessageAtTime(msg, when);
14493 }
14494 }
14495
14496 /**
14497 * Add a process to the array of processes waiting to be GCed. Keeps the
14498 * list in sorted order by the last GC time. The process can't already be
14499 * on the list.
14500 */
14501 final void addProcessToGcListLocked(ProcessRecord proc) {
14502 boolean added = false;
14503 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14504 if (mProcessesToGc.get(i).lastRequestedGc <
14505 proc.lastRequestedGc) {
14506 added = true;
14507 mProcessesToGc.add(i+1, proc);
14508 break;
14509 }
14510 }
14511 if (!added) {
14512 mProcessesToGc.add(0, proc);
14513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014514 }
14515
14516 /**
14517 * Set up to ask a process to GC itself. This will either do it
14518 * immediately, or put it on the list of processes to gc the next
14519 * time things are idle.
14520 */
14521 final void scheduleAppGcLocked(ProcessRecord app) {
14522 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014523 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014524 return;
14525 }
14526 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014527 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014528 scheduleAppGcsLocked();
14529 }
14530 }
14531
14532 private final boolean updateOomAdjLocked(
14533 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14534 app.hiddenAdj = hiddenAdj;
14535
14536 if (app.thread == null) {
14537 return true;
14538 }
14539
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014540 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014541
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014542 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014543 if (app.curRawAdj != app.setRawAdj) {
14544 if (app.curRawAdj > FOREGROUND_APP_ADJ
14545 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14546 // If this app is transitioning from foreground to
14547 // non-foreground, have it do a gc.
14548 scheduleAppGcLocked(app);
14549 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14550 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14551 // Likewise do a gc when an app is moving in to the
14552 // background (such as a service stopping).
14553 scheduleAppGcLocked(app);
14554 }
14555 app.setRawAdj = app.curRawAdj;
14556 }
14557 if (adj != app.setAdj) {
14558 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014559 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014560 TAG, "Set app " + app.processName +
14561 " oom adj to " + adj);
14562 app.setAdj = adj;
14563 } else {
14564 return false;
14565 }
14566 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014567 if (app.setSchedGroup != app.curSchedGroup) {
14568 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014569 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014570 "Setting process group of " + app.processName
14571 + " to " + app.curSchedGroup);
14572 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014573 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014574 try {
14575 Process.setProcessGroup(app.pid, app.curSchedGroup);
14576 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014577 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014578 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014579 e.printStackTrace();
14580 } finally {
14581 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014582 }
14583 }
14584 if (false) {
14585 if (app.thread != null) {
14586 try {
14587 app.thread.setSchedulingGroup(app.curSchedGroup);
14588 } catch (RemoteException e) {
14589 }
14590 }
14591 }
14592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014593 }
14594
14595 return true;
14596 }
14597
14598 private final HistoryRecord resumedAppLocked() {
14599 HistoryRecord resumedActivity = mResumedActivity;
14600 if (resumedActivity == null || resumedActivity.app == null) {
14601 resumedActivity = mPausingActivity;
14602 if (resumedActivity == null || resumedActivity.app == null) {
14603 resumedActivity = topRunningActivityLocked(null);
14604 }
14605 }
14606 return resumedActivity;
14607 }
14608
14609 private final boolean updateOomAdjLocked(ProcessRecord app) {
14610 final HistoryRecord TOP_ACT = resumedAppLocked();
14611 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14612 int curAdj = app.curAdj;
14613 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14614 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14615
14616 mAdjSeq++;
14617
14618 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14619 if (res) {
14620 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14621 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14622 if (nowHidden != wasHidden) {
14623 // Changed to/from hidden state, so apps after it in the LRU
14624 // list may also be changed.
14625 updateOomAdjLocked();
14626 }
14627 }
14628 return res;
14629 }
14630
14631 private final boolean updateOomAdjLocked() {
14632 boolean didOomAdj = true;
14633 final HistoryRecord TOP_ACT = resumedAppLocked();
14634 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14635
14636 if (false) {
14637 RuntimeException e = new RuntimeException();
14638 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014639 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014640 }
14641
14642 mAdjSeq++;
14643
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014644 // Let's determine how many processes we have running vs.
14645 // how many slots we have for background processes; we may want
14646 // to put multiple processes in a slot of there are enough of
14647 // them.
14648 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14649 int factor = (mLruProcesses.size()-4)/numSlots;
14650 if (factor < 1) factor = 1;
14651 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014652 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014654 // First try updating the OOM adjustment for each of the
14655 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014656 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014657 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14658 while (i > 0) {
14659 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014660 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014661 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014662 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014663 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014664 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014665 step++;
14666 if (step >= factor) {
14667 step = 0;
14668 curHiddenAdj++;
14669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014670 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014671 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070014672 if (!app.killedBackground) {
14673 numHidden++;
14674 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070014675 Slog.i(TAG, "No longer want " + app.processName
14676 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014677 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14678 app.processName, app.setAdj, "too many background");
14679 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070014680 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014681 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014682 }
14683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014684 } else {
14685 didOomAdj = false;
14686 }
14687 }
14688
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014689 // If we return false, we will fall back on killing processes to
14690 // have a fixed limit. Do this if a limit has been requested; else
14691 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014692 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14693 }
14694
14695 private final void trimApplications() {
14696 synchronized (this) {
14697 int i;
14698
14699 // First remove any unused application processes whose package
14700 // has been removed.
14701 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14702 final ProcessRecord app = mRemovedProcesses.get(i);
14703 if (app.activities.size() == 0
14704 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014705 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014706 TAG, "Exiting empty application process "
14707 + app.processName + " ("
14708 + (app.thread != null ? app.thread.asBinder() : null)
14709 + ")\n");
14710 if (app.pid > 0 && app.pid != MY_PID) {
14711 Process.killProcess(app.pid);
14712 } else {
14713 try {
14714 app.thread.scheduleExit();
14715 } catch (Exception e) {
14716 // Ignore exceptions.
14717 }
14718 }
14719 cleanUpApplicationRecordLocked(app, false, -1);
14720 mRemovedProcesses.remove(i);
14721
14722 if (app.persistent) {
14723 if (app.persistent) {
14724 addAppLocked(app.info);
14725 }
14726 }
14727 }
14728 }
14729
14730 // Now try updating the OOM adjustment for each of the
14731 // application processes based on their current state.
14732 // If the setOomAdj() API is not supported, then go with our
14733 // back-up plan...
14734 if (!updateOomAdjLocked()) {
14735
14736 // Count how many processes are running services.
14737 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014738 for (i=mLruProcesses.size()-1; i>=0; i--) {
14739 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014740
14741 if (app.persistent || app.services.size() != 0
14742 || app.curReceiver != null
14743 || app.persistentActivities > 0) {
14744 // Don't count processes holding services against our
14745 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014746 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014747 TAG, "Not trimming app " + app + " with services: "
14748 + app.services);
14749 numServiceProcs++;
14750 }
14751 }
14752
14753 int curMaxProcs = mProcessLimit;
14754 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14755 if (mAlwaysFinishActivities) {
14756 curMaxProcs = 1;
14757 }
14758 curMaxProcs += numServiceProcs;
14759
14760 // Quit as many processes as we can to get down to the desired
14761 // process count. First remove any processes that no longer
14762 // have activites running in them.
14763 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014764 i<mLruProcesses.size()
14765 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014766 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014767 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014768 // Quit an application only if it is not currently
14769 // running any activities.
14770 if (!app.persistent && app.activities.size() == 0
14771 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014772 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014773 TAG, "Exiting empty application process "
14774 + app.processName + " ("
14775 + (app.thread != null ? app.thread.asBinder() : null)
14776 + ")\n");
14777 if (app.pid > 0 && app.pid != MY_PID) {
14778 Process.killProcess(app.pid);
14779 } else {
14780 try {
14781 app.thread.scheduleExit();
14782 } catch (Exception e) {
14783 // Ignore exceptions.
14784 }
14785 }
14786 // todo: For now we assume the application is not buggy
14787 // or evil, and will quit as a result of our request.
14788 // Eventually we need to drive this off of the death
14789 // notification, and kill the process if it takes too long.
14790 cleanUpApplicationRecordLocked(app, false, i);
14791 i--;
14792 }
14793 }
14794
14795 // If we still have too many processes, now from the least
14796 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014797 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014798 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014799 " of " + curMaxProcs + " processes");
14800 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014801 i<mLruProcesses.size()
14802 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014803 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014804 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014805 // Quit the application only if we have a state saved for
14806 // all of its activities.
14807 boolean canQuit = !app.persistent && app.curReceiver == null
14808 && app.services.size() == 0
14809 && app.persistentActivities == 0;
14810 int NUMA = app.activities.size();
14811 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014812 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014813 TAG, "Looking to quit " + app.processName);
14814 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014815 HistoryRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014816 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014817 TAG, " " + r.intent.getComponent().flattenToShortString()
14818 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14819 canQuit = (r.haveState || !r.stateNotNeeded)
14820 && !r.visible && r.stopped;
14821 }
14822 if (canQuit) {
14823 // Finish all of the activities, and then the app itself.
14824 for (j=0; j<NUMA; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014825 HistoryRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014826 if (!r.finishing) {
14827 destroyActivityLocked(r, false);
14828 }
14829 r.resultTo = null;
14830 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014831 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014832 + app.processName + " ("
14833 + (app.thread != null ? app.thread.asBinder() : null)
14834 + ")\n");
14835 if (app.pid > 0 && app.pid != MY_PID) {
14836 Process.killProcess(app.pid);
14837 } else {
14838 try {
14839 app.thread.scheduleExit();
14840 } catch (Exception e) {
14841 // Ignore exceptions.
14842 }
14843 }
14844 // todo: For now we assume the application is not buggy
14845 // or evil, and will quit as a result of our request.
14846 // Eventually we need to drive this off of the death
14847 // notification, and kill the process if it takes too long.
14848 cleanUpApplicationRecordLocked(app, false, i);
14849 i--;
14850 //dump();
14851 }
14852 }
14853
14854 }
14855
14856 int curMaxActivities = MAX_ACTIVITIES;
14857 if (mAlwaysFinishActivities) {
14858 curMaxActivities = 1;
14859 }
14860
14861 // Finally, if there are too many activities now running, try to
14862 // finish as many as we can to get back down to the limit.
14863 for ( i=0;
14864 i<mLRUActivities.size()
14865 && mLRUActivities.size() > curMaxActivities;
14866 i++) {
14867 final HistoryRecord r
14868 = (HistoryRecord)mLRUActivities.get(i);
14869
14870 // We can finish this one if we have its icicle saved and
14871 // it is not persistent.
14872 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14873 && r.stopped && !r.persistent && !r.finishing) {
14874 final int origSize = mLRUActivities.size();
14875 destroyActivityLocked(r, true);
14876
14877 // This will remove it from the LRU list, so keep
14878 // our index at the same value. Note that this check to
14879 // see if the size changes is just paranoia -- if
14880 // something unexpected happens, we don't want to end up
14881 // in an infinite loop.
14882 if (origSize > mLRUActivities.size()) {
14883 i--;
14884 }
14885 }
14886 }
14887 }
14888 }
14889
14890 /** This method sends the specified signal to each of the persistent apps */
14891 public void signalPersistentProcesses(int sig) throws RemoteException {
14892 if (sig != Process.SIGNAL_USR1) {
14893 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14894 }
14895
14896 synchronized (this) {
14897 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14898 != PackageManager.PERMISSION_GRANTED) {
14899 throw new SecurityException("Requires permission "
14900 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14901 }
14902
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014903 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14904 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014905 if (r.thread != null && r.persistent) {
14906 Process.sendSignal(r.pid, sig);
14907 }
14908 }
14909 }
14910 }
14911
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014912 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014913 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014914
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014915 try {
14916 synchronized (this) {
14917 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14918 // its own permission.
14919 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14920 != PackageManager.PERMISSION_GRANTED) {
14921 throw new SecurityException("Requires permission "
14922 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014923 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014924
14925 if (start && fd == null) {
14926 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014927 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014928
14929 ProcessRecord proc = null;
14930 try {
14931 int pid = Integer.parseInt(process);
14932 synchronized (mPidsSelfLocked) {
14933 proc = mPidsSelfLocked.get(pid);
14934 }
14935 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014936 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014937
14938 if (proc == null) {
14939 HashMap<String, SparseArray<ProcessRecord>> all
14940 = mProcessNames.getMap();
14941 SparseArray<ProcessRecord> procs = all.get(process);
14942 if (procs != null && procs.size() > 0) {
14943 proc = procs.valueAt(0);
14944 }
14945 }
14946
14947 if (proc == null || proc.thread == null) {
14948 throw new IllegalArgumentException("Unknown process: " + process);
14949 }
14950
14951 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14952 if (isSecure) {
14953 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14954 throw new SecurityException("Process not debuggable: " + proc);
14955 }
14956 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014957
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014958 proc.thread.profilerControl(start, path, fd);
14959 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014960 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014961 }
14962 } catch (RemoteException e) {
14963 throw new IllegalStateException("Process disappeared");
14964 } finally {
14965 if (fd != null) {
14966 try {
14967 fd.close();
14968 } catch (IOException e) {
14969 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014970 }
14971 }
14972 }
14973
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014974 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14975 public void monitor() {
14976 synchronized (this) { }
14977 }
14978}