blob: e81552433a609d9feb676ea7ea1d127bd58272aa [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
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;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
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;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020058import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import 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;
Robert Greenwalt434203a2010-10-11 16:00:27 -070079import android.net.Proxy;
80import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.net.Uri;
82import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080084import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070085import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080088import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.os.FileUtils;
90import android.os.Handler;
91import android.os.IBinder;
92import android.os.IPermissionController;
93import android.os.Looper;
94import android.os.Message;
95import android.os.Parcel;
96import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070098import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.RemoteException;
100import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700101import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.SystemClock;
103import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.util.Config;
106import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800107import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800108import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.util.PrintWriterPrinter;
110import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700111import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import android.view.Gravity;
113import android.view.LayoutInflater;
114import android.view.View;
115import android.view.WindowManager;
116import android.view.WindowManagerPolicy;
117
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700118import java.io.BufferedInputStream;
119import java.io.BufferedOutputStream;
120import java.io.DataInputStream;
121import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122import java.io.File;
123import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700126import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200127import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800128import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.io.PrintWriter;
130import java.lang.IllegalStateException;
131import java.lang.ref.WeakReference;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700132import java.net.InetSocketAddress;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700134import java.util.Collections;
135import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136import java.util.HashMap;
137import java.util.HashSet;
138import java.util.Iterator;
139import java.util.List;
140import java.util.Locale;
141import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700142import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700143import java.util.concurrent.atomic.AtomicBoolean;
144import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700146public final class ActivityManagerService extends ActivityManagerNative
147 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 static final String TAG = "ActivityManager";
149 static final boolean DEBUG = false;
150 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
151 static final boolean DEBUG_SWITCH = localLOGV || false;
152 static final boolean DEBUG_TASKS = localLOGV || false;
153 static final boolean DEBUG_PAUSE = localLOGV || false;
154 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
155 static final boolean DEBUG_TRANSITION = localLOGV || false;
156 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700157 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700159 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 static final boolean DEBUG_VISBILITY = localLOGV || false;
161 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700162 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800163 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700165 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700166 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700167 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700168 static final boolean DEBUG_POWER = localLOGV || false;
169 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 static final boolean VALIDATE_TOKENS = false;
171 static final boolean SHOW_ACTIVITY_START_TIME = true;
172
173 // Control over CPU and battery monitoring.
174 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
175 static final boolean MONITOR_CPU_USAGE = true;
176 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
177 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
178 static final boolean MONITOR_THREAD_CPU_USAGE = false;
179
Dianne Hackborn1655be42009-05-08 14:29:01 -0700180 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700181 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 private static final String SYSTEM_SECURE = "ro.secure";
184
185 // This is the maximum number of application processes we would like
186 // to have running. Due to the asynchronous nature of things, we can
187 // temporarily go beyond this limit.
188 static final int MAX_PROCESSES = 2;
189
190 // Set to false to leave processes running indefinitely, relying on
191 // the kernel killing them as resources are required.
192 static final boolean ENFORCE_PROCESS_LIMIT = false;
193
194 // This is the maximum number of activities that we would like to have
195 // running at a given time.
196 static final int MAX_ACTIVITIES = 20;
197
198 // Maximum number of recent tasks that we can remember.
199 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700200
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700201 // Amount of time after a call to stopAppSwitches() during which we will
202 // prevent further untrusted switches from happening.
203 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204
205 // How long we wait for a launched process to attach to the activity manager
206 // before we decide it's never going to come up for real.
207 static final int PROC_START_TIMEOUT = 10*1000;
208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 // How long to wait after going idle before forcing apps to GC.
210 static final int GC_TIMEOUT = 5*1000;
211
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700212 // The minimum amount of time between successive GC requests for a process.
213 static final int GC_MIN_INTERVAL = 60*1000;
214
Dianne Hackborn287952c2010-09-22 22:34:31 -0700215 // The rate at which we check for apps using excessive power -- 15 mins.
216 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
217
218 // The minimum sample duration we will allow before deciding we have
219 // enough data on wake locks to start killing things.
220 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
221
222 // The minimum sample duration we will allow before deciding we have
223 // enough data on CPU usage to start killing things.
224 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 // 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
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700390 public ActivityStack mMainStack;
391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700393 * Description of a request to start a new activity, which has been held
394 * due to app switches being disabled.
395 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700396 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700397 ActivityRecord r;
398 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700399 Uri[] grantedUriPermissions;
400 int grantedMode;
401 boolean onlyIfNeeded;
402 }
403
404 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
405 = new ArrayList<PendingActivityLaunch>();
406
407 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * List of all active broadcasts that are to be executed immediately
409 * (without waiting for another broadcast to finish). Currently this only
410 * contains broadcasts to registered receivers, to avoid spinning up
411 * a bunch of processes to execute IntentReceiver components.
412 */
413 final ArrayList<BroadcastRecord> mParallelBroadcasts
414 = new ArrayList<BroadcastRecord>();
415
416 /**
417 * List of all active broadcasts that are to be executed one at a time.
418 * The object at the top of the list is the currently activity broadcasts;
419 * those after it are waiting for the top to finish..
420 */
421 final ArrayList<BroadcastRecord> mOrderedBroadcasts
422 = new ArrayList<BroadcastRecord>();
423
424 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800425 * Historical data of past broadcasts, for debugging.
426 */
427 static final int MAX_BROADCAST_HISTORY = 100;
428 final BroadcastRecord[] mBroadcastHistory
429 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
430
431 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 * Set when we current have a BROADCAST_INTENT_MSG in flight.
433 */
434 boolean mBroadcastsScheduled = false;
435
436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * Activity we have told the window manager to have key focus.
438 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700439 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700440 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 * List of intents that were used to start the most recent tasks.
442 */
443 final ArrayList<TaskRecord> mRecentTasks
444 = new ArrayList<TaskRecord>();
445
446 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 * All of the applications we currently have running organized by name.
448 * The keys are strings of the application package name (as
449 * returned by the package manager), and the keys are ApplicationRecord
450 * objects.
451 */
452 final ProcessMap<ProcessRecord> mProcessNames
453 = new ProcessMap<ProcessRecord>();
454
455 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700456 * The currently running heavy-weight process, if any.
457 */
458 ProcessRecord mHeavyWeightProcess = null;
459
460 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 * The last time that various processes have crashed.
462 */
463 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
464
465 /**
466 * Set of applications that we consider to be bad, and will reject
467 * incoming broadcasts from (which the user has no control over).
468 * Processes are added to this set when they have crashed twice within
469 * a minimum amount of time; they are removed from it when they are
470 * later restarted (hopefully due to some user action). The value is the
471 * time it was added to the list.
472 */
473 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
474
475 /**
476 * All of the processes we currently have running organized by pid.
477 * The keys are the pid running the application.
478 *
479 * <p>NOTE: This object is protected by its own lock, NOT the global
480 * activity manager lock!
481 */
482 final SparseArray<ProcessRecord> mPidsSelfLocked
483 = new SparseArray<ProcessRecord>();
484
485 /**
486 * All of the processes that have been forced to be foreground. The key
487 * is the pid of the caller who requested it (we hold a death
488 * link on it).
489 */
490 abstract class ForegroundToken implements IBinder.DeathRecipient {
491 int pid;
492 IBinder token;
493 }
494 final SparseArray<ForegroundToken> mForegroundProcesses
495 = new SparseArray<ForegroundToken>();
496
497 /**
498 * List of records for processes that someone had tried to start before the
499 * system was ready. We don't start them at that point, but ensure they
500 * are started by the time booting is complete.
501 */
502 final ArrayList<ProcessRecord> mProcessesOnHold
503 = new ArrayList<ProcessRecord>();
504
505 /**
506 * List of records for processes that we have started and are waiting
507 * for them to call back. This is really only needed when running in
508 * single processes mode, in which case we do not have a unique pid for
509 * each process.
510 */
511 final ArrayList<ProcessRecord> mStartingProcesses
512 = new ArrayList<ProcessRecord>();
513
514 /**
515 * List of persistent applications that are in the process
516 * of being started.
517 */
518 final ArrayList<ProcessRecord> mPersistentStartingProcesses
519 = new ArrayList<ProcessRecord>();
520
521 /**
522 * Processes that are being forcibly torn down.
523 */
524 final ArrayList<ProcessRecord> mRemovedProcesses
525 = new ArrayList<ProcessRecord>();
526
527 /**
528 * List of running applications, sorted by recent usage.
529 * The first entry in the list is the least recently used.
530 * It contains ApplicationRecord objects. This list does NOT include
531 * any persistent application records (since we never want to exit them).
532 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800533 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 = new ArrayList<ProcessRecord>();
535
536 /**
537 * List of processes that should gc as soon as things are idle.
538 */
539 final ArrayList<ProcessRecord> mProcessesToGc
540 = new ArrayList<ProcessRecord>();
541
542 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800543 * This is the process holding what we currently consider to be
544 * the "home" activity.
545 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700546 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800547
548 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 * Set of PendingResultRecord objects that are currently active.
550 */
551 final HashSet mPendingResultRecords = new HashSet();
552
553 /**
554 * Set of IntentSenderRecord objects that are currently active.
555 */
556 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
557 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
558
559 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700560 * Fingerprints (String.hashCode()) of stack traces that we've
561 * already logged DropBox entries for. Guarded by itself. If
562 * something (rogue user app) forces this over
563 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
564 */
565 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
566 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
567
568 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700569 * Strict Mode background batched logging state.
570 *
571 * The string buffer is guarded by itself, and its lock is also
572 * used to determine if another batched write is already
573 * in-flight.
574 */
575 private final StringBuilder mStrictModeBuffer = new StringBuilder();
576
577 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700578 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
579 */
580 private boolean mPendingBroadcastTimeoutMessage;
581
582 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 * Intent broadcast that we have tried to start, but are
584 * waiting for its application's process to be created. We only
585 * need one (instead of a list) because we always process broadcasts
586 * one at a time, so no others can be started while waiting for this
587 * one.
588 */
589 BroadcastRecord mPendingBroadcast = null;
590
591 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700592 * The receiver index that is pending, to restart the broadcast if needed.
593 */
594 int mPendingBroadcastRecvIndex;
595
596 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 * Keeps track of all IIntentReceivers that have been registered for
598 * broadcasts. Hash keys are the receiver IBinder, hash value is
599 * a ReceiverList.
600 */
601 final HashMap mRegisteredReceivers = new HashMap();
602
603 /**
604 * Resolver for broadcast intents to registered receivers.
605 * Holds BroadcastFilter (subclass of IntentFilter).
606 */
607 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
608 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
609 @Override
610 protected boolean allowFilterResult(
611 BroadcastFilter filter, List<BroadcastFilter> dest) {
612 IBinder target = filter.receiverList.receiver.asBinder();
613 for (int i=dest.size()-1; i>=0; i--) {
614 if (dest.get(i).receiverList.receiver.asBinder() == target) {
615 return false;
616 }
617 }
618 return true;
619 }
620 };
621
622 /**
623 * State of all active sticky broadcasts. Keys are the action of the
624 * sticky Intent, values are an ArrayList of all broadcasted intents with
625 * that action (which should usually be one).
626 */
627 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
628 new HashMap<String, ArrayList<Intent>>();
629
630 /**
631 * All currently running services.
632 */
633 final HashMap<ComponentName, ServiceRecord> mServices =
634 new HashMap<ComponentName, ServiceRecord>();
635
636 /**
637 * All currently running services indexed by the Intent used to start them.
638 */
639 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
640 new HashMap<Intent.FilterComparison, ServiceRecord>();
641
642 /**
643 * All currently bound service connections. Keys are the IBinder of
644 * the client's IServiceConnection.
645 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700646 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
647 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648
649 /**
650 * List of services that we have been asked to start,
651 * but haven't yet been able to. It is used to hold start requests
652 * while waiting for their corresponding application thread to get
653 * going.
654 */
655 final ArrayList<ServiceRecord> mPendingServices
656 = new ArrayList<ServiceRecord>();
657
658 /**
659 * List of services that are scheduled to restart following a crash.
660 */
661 final ArrayList<ServiceRecord> mRestartingServices
662 = new ArrayList<ServiceRecord>();
663
664 /**
665 * List of services that are in the process of being stopped.
666 */
667 final ArrayList<ServiceRecord> mStoppingServices
668 = new ArrayList<ServiceRecord>();
669
670 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700671 * Backup/restore process management
672 */
673 String mBackupAppName = null;
674 BackupRecord mBackupTarget = null;
675
676 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677 * List of PendingThumbnailsRecord objects of clients who are still
678 * waiting to receive all of the thumbnails for a task.
679 */
680 final ArrayList mPendingThumbnails = new ArrayList();
681
682 /**
683 * List of HistoryRecord objects that have been finished and must
684 * still report back to a pending thumbnail receiver.
685 */
686 final ArrayList mCancelledThumbnails = new ArrayList();
687
688 /**
689 * All of the currently running global content providers. Keys are a
690 * string containing the provider name and values are a
691 * ContentProviderRecord object containing the data about it. Note
692 * that a single provider may be published under multiple names, so
693 * there may be multiple entries here for a single one in mProvidersByClass.
694 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700695 final HashMap<String, ContentProviderRecord> mProvidersByName
696 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697
698 /**
699 * All of the currently running global content providers. Keys are a
700 * string containing the provider's implementation class and values are a
701 * ContentProviderRecord object containing the data about it.
702 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700703 final HashMap<String, ContentProviderRecord> mProvidersByClass
704 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705
706 /**
707 * List of content providers who have clients waiting for them. The
708 * application is currently being launched and the provider will be
709 * removed from this list once it is published.
710 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700711 final ArrayList<ContentProviderRecord> mLaunchingProviders
712 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713
714 /**
715 * Global set of specific Uri permissions that have been granted.
716 */
717 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
718 = new SparseArray<HashMap<Uri, UriPermission>>();
719
720 /**
721 * Thread-local storage used to carry caller permissions over through
722 * indirect content-provider access.
723 * @see #ActivityManagerService.openContentUri()
724 */
725 private class Identity {
726 public int pid;
727 public int uid;
728
729 Identity(int _pid, int _uid) {
730 pid = _pid;
731 uid = _uid;
732 }
733 }
734 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
735
736 /**
737 * All information we have collected about the runtime performance of
738 * any user id that can impact battery performance.
739 */
740 final BatteryStatsService mBatteryStatsService;
741
742 /**
743 * information about component usage
744 */
745 final UsageStatsService mUsageStatsService;
746
747 /**
748 * Current configuration information. HistoryRecord objects are given
749 * a reference to this object to indicate which configuration they are
750 * currently running in, so this object must be kept immutable.
751 */
752 Configuration mConfiguration = new Configuration();
753
754 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800755 * Current sequencing integer of the configuration, for skipping old
756 * configurations.
757 */
758 int mConfigurationSeq = 0;
759
760 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700761 * Hardware-reported OpenGLES version.
762 */
763 final int GL_ES_VERSION;
764
765 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 * List of initialization arguments to pass to all processes when binding applications to them.
767 * For example, references to the commonly used services.
768 */
769 HashMap<String, IBinder> mAppBindArgs;
770
771 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700772 * Temporary to avoid allocations. Protected by main lock.
773 */
774 final StringBuilder mStringBuilder = new StringBuilder(256);
775
776 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 * Used to control how we initialize the service.
778 */
779 boolean mStartRunning = false;
780 ComponentName mTopComponent;
781 String mTopAction;
782 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700783 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 boolean mSystemReady = false;
785 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700786 boolean mWaitingUpdate = false;
787 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700788 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700789 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790
791 Context mContext;
792
793 int mFactoryTest;
794
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700795 boolean mCheckedForSetup;
796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700798 * The time at which we will allow normal application switches again,
799 * after a call to {@link #stopAppSwitches()}.
800 */
801 long mAppSwitchesAllowedTime;
802
803 /**
804 * This is set to true after the first switch after mAppSwitchesAllowedTime
805 * is set; any switches after that will clear the time.
806 */
807 boolean mDidAppSwitch;
808
809 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700810 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700811 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700812 long mLastPowerCheckRealtime;
813
814 /**
815 * Last time (in uptime) at which we checked for power usage.
816 */
817 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700818
819 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 * Set while we are wanting to sleep, to prevent any
821 * activities from being started/resumed.
822 */
823 boolean mSleeping = false;
824
825 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700826 * Set if we are shutting down the system, similar to sleeping.
827 */
828 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829
830 /**
831 * Task identifier that activities are currently being started
832 * in. Incremented each time a new task is created.
833 * todo: Replace this with a TokenSpace class that generates non-repeating
834 * integers that won't wrap.
835 */
836 int mCurTask = 1;
837
838 /**
839 * Current sequence id for oom_adj computation traversal.
840 */
841 int mAdjSeq = 0;
842
843 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700844 * Current sequence id for process LRU updating.
845 */
846 int mLruSeq = 0;
847
848 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
850 * is set, indicating the user wants processes started in such a way
851 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
852 * running in each process (thus no pre-initialized process, etc).
853 */
854 boolean mSimpleProcessManagement = false;
855
856 /**
857 * System monitoring: number of processes that died since the last
858 * N procs were started.
859 */
860 int[] mProcDeaths = new int[20];
861
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700862 /**
863 * This is set if we had to do a delayed dexopt of an app before launching
864 * it, to increasing the ANR timeouts in that case.
865 */
866 boolean mDidDexOpt;
867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 String mDebugApp = null;
869 boolean mWaitForDebugger = false;
870 boolean mDebugTransient = false;
871 String mOrigDebugApp = null;
872 boolean mOrigWaitForDebugger = false;
873 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700874 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700876 final RemoteCallbackList<IActivityWatcher> mWatchers
877 = new RemoteCallbackList<IActivityWatcher>();
878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 /**
880 * Callback of last caller to {@link #requestPss}.
881 */
882 Runnable mRequestPssCallback;
883
884 /**
885 * Remaining processes for which we are waiting results from the last
886 * call to {@link #requestPss}.
887 */
888 final ArrayList<ProcessRecord> mRequestPssList
889 = new ArrayList<ProcessRecord>();
890
891 /**
892 * Runtime statistics collection thread. This object's lock is used to
893 * protect all related state.
894 */
895 final Thread mProcessStatsThread;
896
897 /**
898 * Used to collect process stats when showing not responding dialog.
899 * Protected by mProcessStatsThread.
900 */
901 final ProcessStats mProcessStats = new ProcessStats(
902 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700903 final AtomicLong mLastCpuTime = new AtomicLong(0);
904 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 long mLastWriteTime = 0;
907
908 /**
909 * Set to true after the system has finished booting.
910 */
911 boolean mBooted = false;
912
913 int mProcessLimit = 0;
914
915 WindowManagerService mWindowManager;
916
917 static ActivityManagerService mSelf;
918 static ActivityThread mSystemThread;
919
920 private final class AppDeathRecipient implements IBinder.DeathRecipient {
921 final ProcessRecord mApp;
922 final int mPid;
923 final IApplicationThread mAppThread;
924
925 AppDeathRecipient(ProcessRecord app, int pid,
926 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800927 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 TAG, "New death recipient " + this
929 + " for thread " + thread.asBinder());
930 mApp = app;
931 mPid = pid;
932 mAppThread = thread;
933 }
934
935 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800936 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 TAG, "Death received in " + this
938 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 synchronized(ActivityManagerService.this) {
940 appDiedLocked(mApp, mPid, mAppThread);
941 }
942 }
943 }
944
945 static final int SHOW_ERROR_MSG = 1;
946 static final int SHOW_NOT_RESPONDING_MSG = 2;
947 static final int SHOW_FACTORY_ERROR_MSG = 3;
948 static final int UPDATE_CONFIGURATION_MSG = 4;
949 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
950 static final int WAIT_FOR_DEBUGGER_MSG = 6;
951 static final int BROADCAST_INTENT_MSG = 7;
952 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 static final int SERVICE_TIMEOUT_MSG = 12;
954 static final int UPDATE_TIME_ZONE = 13;
955 static final int SHOW_UID_ERROR_MSG = 14;
956 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700958 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700959 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800960 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700961 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
962 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700963 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700964 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700965 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700966 static final int UPDATE_HTTP_PROXY = 29;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967
968 AlertDialog mUidAlert;
969
970 final Handler mHandler = new Handler() {
971 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800972 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 //}
974
975 public void handleMessage(Message msg) {
976 switch (msg.what) {
977 case SHOW_ERROR_MSG: {
978 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 synchronized (ActivityManagerService.this) {
980 ProcessRecord proc = (ProcessRecord)data.get("app");
981 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800982 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 return;
984 }
985 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700986 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800987 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 d.show();
989 proc.crashDialog = d;
990 } else {
991 // The device is asleep, so just pretend that the user
992 // saw a crash dialog and hit "force quit".
993 res.set(0);
994 }
995 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700996
997 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 } break;
999 case SHOW_NOT_RESPONDING_MSG: {
1000 synchronized (ActivityManagerService.this) {
1001 HashMap data = (HashMap) msg.obj;
1002 ProcessRecord proc = (ProcessRecord)data.get("app");
1003 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001004 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 return;
1006 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001007
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001008 Intent intent = new Intent("android.intent.action.ANR");
1009 if (!mProcessesReady) {
1010 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1011 }
1012 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001013 null, null, 0, null, null, null,
1014 false, false, MY_PID, Process.SYSTEM_UID);
1015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001017 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 d.show();
1019 proc.anrDialog = d;
1020 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001021
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001022 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001024 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1025 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1026 synchronized (ActivityManagerService.this) {
1027 ProcessRecord proc = (ProcessRecord) data.get("app");
1028 if (proc == null) {
1029 Slog.e(TAG, "App not found when showing strict mode dialog.");
1030 break;
1031 }
1032 if (proc.crashDialog != null) {
1033 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1034 return;
1035 }
1036 AppErrorResult res = (AppErrorResult) data.get("result");
1037 if (!mSleeping && !mShuttingDown) {
1038 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1039 d.show();
1040 proc.crashDialog = d;
1041 } else {
1042 // The device is asleep, so just pretend that the user
1043 // saw a crash dialog and hit "force quit".
1044 res.set(0);
1045 }
1046 }
1047 ensureBootCompleted();
1048 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 case SHOW_FACTORY_ERROR_MSG: {
1050 Dialog d = new FactoryErrorDialog(
1051 mContext, msg.getData().getCharSequence("msg"));
1052 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001053 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 } break;
1055 case UPDATE_CONFIGURATION_MSG: {
1056 final ContentResolver resolver = mContext.getContentResolver();
1057 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1058 } break;
1059 case GC_BACKGROUND_PROCESSES_MSG: {
1060 synchronized (ActivityManagerService.this) {
1061 performAppGcsIfAppropriateLocked();
1062 }
1063 } break;
1064 case WAIT_FOR_DEBUGGER_MSG: {
1065 synchronized (ActivityManagerService.this) {
1066 ProcessRecord app = (ProcessRecord)msg.obj;
1067 if (msg.arg1 != 0) {
1068 if (!app.waitedForDebugger) {
1069 Dialog d = new AppWaitingForDebuggerDialog(
1070 ActivityManagerService.this,
1071 mContext, app);
1072 app.waitDialog = d;
1073 app.waitedForDebugger = true;
1074 d.show();
1075 }
1076 } else {
1077 if (app.waitDialog != null) {
1078 app.waitDialog.dismiss();
1079 app.waitDialog = null;
1080 }
1081 }
1082 }
1083 } break;
1084 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001085 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 TAG, "Received BROADCAST_INTENT_MSG");
1087 processNextBroadcast(true);
1088 } break;
1089 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001090 synchronized (ActivityManagerService.this) {
1091 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001095 if (mDidDexOpt) {
1096 mDidDexOpt = false;
1097 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1098 nmsg.obj = msg.obj;
1099 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1100 return;
1101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 serviceTimeout((ProcessRecord)msg.obj);
1103 } break;
1104 case UPDATE_TIME_ZONE: {
1105 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001106 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1107 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 if (r.thread != null) {
1109 try {
1110 r.thread.updateTimeZone();
1111 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001112 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 }
1114 }
1115 }
1116 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001117 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001118 case CLEAR_DNS_CACHE: {
1119 synchronized (ActivityManagerService.this) {
1120 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1121 ProcessRecord r = mLruProcesses.get(i);
1122 if (r.thread != null) {
1123 try {
1124 r.thread.clearDnsCache();
1125 } catch (RemoteException ex) {
1126 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1127 }
1128 }
1129 }
1130 }
1131 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001132 case UPDATE_HTTP_PROXY: {
1133 ProxyProperties proxy = (ProxyProperties)msg.obj;
1134 String host = "";
1135 String port = "";
1136 String exclList = "";
1137 if (proxy != null) {
1138 host = proxy.getHost();
1139 port = Integer.toString(proxy.getPort());
1140 exclList = proxy.getExclusionList();
1141 }
1142 synchronized (ActivityManagerService.this) {
1143 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1144 ProcessRecord r = mLruProcesses.get(i);
1145 if (r.thread != null) {
1146 try {
1147 r.thread.setHttpProxy(host, port, exclList);
1148 } catch (RemoteException ex) {
1149 Slog.w(TAG, "Failed to update http proxy for: " +
1150 r.info.processName);
1151 }
1152 }
1153 }
1154 }
1155 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 case SHOW_UID_ERROR_MSG: {
1157 // XXX This is a temporary dialog, no need to localize.
1158 AlertDialog d = new BaseErrorDialog(mContext);
1159 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1160 d.setCancelable(false);
1161 d.setTitle("System UIDs Inconsistent");
1162 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
Christian Mehlmauer7664e202010-07-20 08:46:17 +02001163 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1165 mUidAlert = d;
1166 d.show();
1167 } break;
1168 case IM_FEELING_LUCKY_MSG: {
1169 if (mUidAlert != null) {
1170 mUidAlert.dismiss();
1171 mUidAlert = null;
1172 }
1173 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001175 if (mDidDexOpt) {
1176 mDidDexOpt = false;
1177 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1178 nmsg.obj = msg.obj;
1179 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1180 return;
1181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 ProcessRecord app = (ProcessRecord)msg.obj;
1183 synchronized (ActivityManagerService.this) {
1184 processStartTimedOutLocked(app);
1185 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001186 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001187 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1188 synchronized (ActivityManagerService.this) {
1189 doPendingActivityLaunchesLocked(true);
1190 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001191 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001192 case KILL_APPLICATION_MSG: {
1193 synchronized (ActivityManagerService.this) {
1194 int uid = msg.arg1;
1195 boolean restart = (msg.arg2 == 1);
1196 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001197 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001198 }
1199 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001200 case FINALIZE_PENDING_INTENT_MSG: {
1201 ((PendingIntentRecord)msg.obj).completeFinalize();
1202 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001203 case POST_HEAVY_NOTIFICATION_MSG: {
1204 INotificationManager inm = NotificationManager.getService();
1205 if (inm == null) {
1206 return;
1207 }
1208
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001209 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001210 ProcessRecord process = root.app;
1211 if (process == null) {
1212 return;
1213 }
1214
1215 try {
1216 Context context = mContext.createPackageContext(process.info.packageName, 0);
1217 String text = mContext.getString(R.string.heavy_weight_notification,
1218 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1219 Notification notification = new Notification();
1220 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1221 notification.when = 0;
1222 notification.flags = Notification.FLAG_ONGOING_EVENT;
1223 notification.tickerText = text;
1224 notification.defaults = 0; // please be quiet
1225 notification.sound = null;
1226 notification.vibrate = null;
1227 notification.setLatestEventInfo(context, text,
1228 mContext.getText(R.string.heavy_weight_notification_detail),
1229 PendingIntent.getActivity(mContext, 0, root.intent,
1230 PendingIntent.FLAG_CANCEL_CURRENT));
1231
1232 try {
1233 int[] outId = new int[1];
1234 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1235 notification, outId);
1236 } catch (RuntimeException e) {
1237 Slog.w(ActivityManagerService.TAG,
1238 "Error showing notification for heavy-weight app", e);
1239 } catch (RemoteException e) {
1240 }
1241 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001242 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001243 }
1244 } break;
1245 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1246 INotificationManager inm = NotificationManager.getService();
1247 if (inm == null) {
1248 return;
1249 }
1250 try {
1251 inm.cancelNotification("android",
1252 R.string.heavy_weight_notification);
1253 } catch (RuntimeException e) {
1254 Slog.w(ActivityManagerService.TAG,
1255 "Error canceling notification for service", e);
1256 } catch (RemoteException e) {
1257 }
1258 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001259 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1260 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001261 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001262 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001263 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1264 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001265 }
1266 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 }
1268 }
1269 };
1270
1271 public static void setSystemProcess() {
1272 try {
1273 ActivityManagerService m = mSelf;
1274
1275 ServiceManager.addService("activity", m);
1276 ServiceManager.addService("meminfo", new MemBinder(m));
1277 if (MONITOR_CPU_USAGE) {
1278 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001280 ServiceManager.addService("permission", new PermissionController(m));
1281
1282 ApplicationInfo info =
1283 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001284 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001285 mSystemThread.installSystemApplicationInfo(info);
1286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 synchronized (mSelf) {
1288 ProcessRecord app = mSelf.newProcessRecordLocked(
1289 mSystemThread.getApplicationThread(), info,
1290 info.processName);
1291 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001292 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293 app.maxAdj = SYSTEM_ADJ;
1294 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1295 synchronized (mSelf.mPidsSelfLocked) {
1296 mSelf.mPidsSelfLocked.put(app.pid, app);
1297 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001298 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 }
1300 } catch (PackageManager.NameNotFoundException e) {
1301 throw new RuntimeException(
1302 "Unable to find android system package", e);
1303 }
1304 }
1305
1306 public void setWindowManager(WindowManagerService wm) {
1307 mWindowManager = wm;
1308 }
1309
1310 public static final Context main(int factoryTest) {
1311 AThread thr = new AThread();
1312 thr.start();
1313
1314 synchronized (thr) {
1315 while (thr.mService == null) {
1316 try {
1317 thr.wait();
1318 } catch (InterruptedException e) {
1319 }
1320 }
1321 }
1322
1323 ActivityManagerService m = thr.mService;
1324 mSelf = m;
1325 ActivityThread at = ActivityThread.systemMain();
1326 mSystemThread = at;
1327 Context context = at.getSystemContext();
1328 m.mContext = context;
1329 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001330 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331
1332 m.mBatteryStatsService.publish(context);
1333 m.mUsageStatsService.publish(context);
1334
1335 synchronized (thr) {
1336 thr.mReady = true;
1337 thr.notifyAll();
1338 }
1339
1340 m.startRunning(null, null, null, null);
1341
1342 return context;
1343 }
1344
1345 public static ActivityManagerService self() {
1346 return mSelf;
1347 }
1348
1349 static class AThread extends Thread {
1350 ActivityManagerService mService;
1351 boolean mReady = false;
1352
1353 public AThread() {
1354 super("ActivityManager");
1355 }
1356
1357 public void run() {
1358 Looper.prepare();
1359
1360 android.os.Process.setThreadPriority(
1361 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001362 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363
1364 ActivityManagerService m = new ActivityManagerService();
1365
1366 synchronized (this) {
1367 mService = m;
1368 notifyAll();
1369 }
1370
1371 synchronized (this) {
1372 while (!mReady) {
1373 try {
1374 wait();
1375 } catch (InterruptedException e) {
1376 }
1377 }
1378 }
1379
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001380 // For debug builds, log event loop stalls to dropbox for analysis.
1381 if (StrictMode.conditionallyEnableDebugLogging()) {
1382 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1383 }
1384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 Looper.loop();
1386 }
1387 }
1388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 static class MemBinder extends Binder {
1390 ActivityManagerService mActivityManagerService;
1391 MemBinder(ActivityManagerService activityManagerService) {
1392 mActivityManagerService = activityManagerService;
1393 }
1394
1395 @Override
1396 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1397 ActivityManagerService service = mActivityManagerService;
1398 ArrayList<ProcessRecord> procs;
1399 synchronized (mActivityManagerService) {
1400 if (args != null && args.length > 0
1401 && args[0].charAt(0) != '-') {
1402 procs = new ArrayList<ProcessRecord>();
1403 int pid = -1;
1404 try {
1405 pid = Integer.parseInt(args[0]);
1406 } catch (NumberFormatException e) {
1407
1408 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001409 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1410 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 if (proc.pid == pid) {
1412 procs.add(proc);
1413 } else if (proc.processName.equals(args[0])) {
1414 procs.add(proc);
1415 }
1416 }
1417 if (procs.size() <= 0) {
1418 pw.println("No process found for: " + args[0]);
1419 return;
1420 }
1421 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001422 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
1424 }
1425 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1426 }
1427 }
1428
1429 static class CpuBinder extends Binder {
1430 ActivityManagerService mActivityManagerService;
1431 CpuBinder(ActivityManagerService activityManagerService) {
1432 mActivityManagerService = activityManagerService;
1433 }
1434
1435 @Override
1436 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1437 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001438 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1439 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1440 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 }
1442 }
1443 }
1444
1445 private ActivityManagerService() {
1446 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1447 if (v != null && Integer.getInteger(v) != 0) {
1448 mSimpleProcessManagement = true;
1449 }
1450 v = System.getenv("ANDROID_DEBUG_APP");
1451 if (v != null) {
1452 mSimpleProcessManagement = true;
1453 }
1454
Joe Onorato8a9b2202010-02-26 18:56:32 -08001455 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 File dataDir = Environment.getDataDirectory();
1458 File systemDir = new File(dataDir, "system");
1459 systemDir.mkdirs();
1460 mBatteryStatsService = new BatteryStatsService(new File(
1461 systemDir, "batterystats.bin").toString());
1462 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001463 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001464 mOnBattery = DEBUG_POWER ? true
1465 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001466 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001468 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001469 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470
Jack Palevichb90d28c2009-07-22 15:35:24 -07001471 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1472 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1473
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001474 mConfiguration.setToDefaults();
1475 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 mProcessStats.init();
1477
1478 // Add ourself to the Watchdog monitors.
1479 Watchdog.getInstance().addMonitor(this);
1480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 mProcessStatsThread = new Thread("ProcessStats") {
1482 public void run() {
1483 while (true) {
1484 try {
1485 try {
1486 synchronized(this) {
1487 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001488 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001490 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 // + ", write delay=" + nextWriteDelay);
1492 if (nextWriteDelay < nextCpuDelay) {
1493 nextCpuDelay = nextWriteDelay;
1494 }
1495 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001496 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 this.wait(nextCpuDelay);
1498 }
1499 }
1500 } catch (InterruptedException e) {
1501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 updateCpuStatsNow();
1503 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001504 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 }
1506 }
1507 }
1508 };
1509 mProcessStatsThread.start();
1510 }
1511
1512 @Override
1513 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1514 throws RemoteException {
1515 try {
1516 return super.onTransact(code, data, reply, flags);
1517 } catch (RuntimeException e) {
1518 // The activity manager only throws security exceptions, so let's
1519 // log all others.
1520 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001521 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 }
1523 throw e;
1524 }
1525 }
1526
1527 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001528 final long now = SystemClock.uptimeMillis();
1529 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1530 return;
1531 }
1532 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1533 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 mProcessStatsThread.notify();
1535 }
1536 }
1537 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 void updateCpuStatsNow() {
1540 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001541 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 final long now = SystemClock.uptimeMillis();
1543 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001546 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1547 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 haveNewCpuStats = true;
1549 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001550 //Slog.i(TAG, mProcessStats.printCurrentState());
1551 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 // + mProcessStats.getTotalCpuPercent() + "%");
1553
Joe Onorato8a9b2202010-02-26 18:56:32 -08001554 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 if ("true".equals(SystemProperties.get("events.cpu"))) {
1556 int user = mProcessStats.getLastUserTime();
1557 int system = mProcessStats.getLastSystemTime();
1558 int iowait = mProcessStats.getLastIoWaitTime();
1559 int irq = mProcessStats.getLastIrqTime();
1560 int softIrq = mProcessStats.getLastSoftIrqTime();
1561 int idle = mProcessStats.getLastIdleTime();
1562
1563 int total = user + system + iowait + irq + softIrq + idle;
1564 if (total == 0) total = 1;
1565
Doug Zongker2bec3d42009-12-04 12:52:44 -08001566 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 ((user+system+iowait+irq+softIrq) * 100) / total,
1568 (user * 100) / total,
1569 (system * 100) / total,
1570 (iowait * 100) / total,
1571 (irq * 100) / total,
1572 (softIrq * 100) / total);
1573 }
1574 }
1575
Amith Yamasanie43530a2009-08-21 13:11:37 -07001576 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001577 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001578 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 synchronized(mPidsSelfLocked) {
1580 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001581 if (mOnBattery) {
1582 int perc = bstats.startAddingCpuLocked();
1583 int totalUTime = 0;
1584 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001585 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001587 ProcessStats.Stats st = mProcessStats.getStats(i);
1588 if (!st.working) {
1589 continue;
1590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001592 int otherUTime = (st.rel_utime*perc)/100;
1593 int otherSTime = (st.rel_stime*perc)/100;
1594 totalUTime += otherUTime;
1595 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 if (pr != null) {
1597 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001598 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1599 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001600 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001601 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001602 } else {
1603 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001604 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001605 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001606 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1607 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001608 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 }
1611 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001612 bstats.finishAddingCpuLocked(perc, totalUTime,
1613 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 }
1615 }
1616 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1619 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001620 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 }
1622 }
1623 }
1624 }
1625
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001626 @Override
1627 public void batteryNeedsCpuUpdate() {
1628 updateCpuStatsNow();
1629 }
1630
1631 @Override
1632 public void batteryPowerChanged(boolean onBattery) {
1633 // When plugging in, update the CPU stats first before changing
1634 // the plug state.
1635 updateCpuStatsNow();
1636 synchronized (this) {
1637 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001638 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001639 }
1640 }
1641 }
1642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 /**
1644 * Initialize the application bind args. These are passed to each
1645 * process when the bindApplication() IPC is sent to the process. They're
1646 * lazily setup to make sure the services are running when they're asked for.
1647 */
1648 private HashMap<String, IBinder> getCommonServicesLocked() {
1649 if (mAppBindArgs == null) {
1650 mAppBindArgs = new HashMap<String, IBinder>();
1651
1652 // Setup the application init args
1653 mAppBindArgs.put("package", ServiceManager.getService("package"));
1654 mAppBindArgs.put("window", ServiceManager.getService("window"));
1655 mAppBindArgs.put(Context.ALARM_SERVICE,
1656 ServiceManager.getService(Context.ALARM_SERVICE));
1657 }
1658 return mAppBindArgs;
1659 }
1660
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001661 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 if (mFocusedActivity != r) {
1663 mFocusedActivity = r;
1664 mWindowManager.setFocusedApp(r, true);
1665 }
1666 }
1667
Dianne Hackborn906497c2010-05-10 15:57:38 -07001668 private final void updateLruProcessInternalLocked(ProcessRecord app,
1669 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001671 int lrui = mLruProcesses.indexOf(app);
1672 if (lrui >= 0) mLruProcesses.remove(lrui);
1673
1674 int i = mLruProcesses.size()-1;
1675 int skipTop = 0;
1676
Dianne Hackborn906497c2010-05-10 15:57:38 -07001677 app.lruSeq = mLruSeq;
1678
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001679 // compute the new weight for this process.
1680 if (updateActivityTime) {
1681 app.lastActivityTime = SystemClock.uptimeMillis();
1682 }
1683 if (app.activities.size() > 0) {
1684 // If this process has activities, we more strongly want to keep
1685 // it around.
1686 app.lruWeight = app.lastActivityTime;
1687 } else if (app.pubProviders.size() > 0) {
1688 // If this process contains content providers, we want to keep
1689 // it a little more strongly.
1690 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1691 // Also don't let it kick out the first few "real" hidden processes.
1692 skipTop = MIN_HIDDEN_APPS;
1693 } else {
1694 // If this process doesn't have activities, we less strongly
1695 // want to keep it around, and generally want to avoid getting
1696 // in front of any very recently used activities.
1697 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1698 // Also don't let it kick out the first few "real" hidden processes.
1699 skipTop = MIN_HIDDEN_APPS;
1700 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001701
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001702 while (i >= 0) {
1703 ProcessRecord p = mLruProcesses.get(i);
1704 // If this app shouldn't be in front of the first N background
1705 // apps, then skip over that many that are currently hidden.
1706 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1707 skipTop--;
1708 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001709 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001710 mLruProcesses.add(i+1, app);
1711 break;
1712 }
1713 i--;
1714 }
1715 if (i < 0) {
1716 mLruProcesses.add(0, app);
1717 }
1718
Dianne Hackborn906497c2010-05-10 15:57:38 -07001719 // If the app is currently using a content provider or service,
1720 // bump those processes as well.
1721 if (app.connections.size() > 0) {
1722 for (ConnectionRecord cr : app.connections) {
1723 if (cr.binding != null && cr.binding.service != null
1724 && cr.binding.service.app != null
1725 && cr.binding.service.app.lruSeq != mLruSeq) {
1726 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1727 updateActivityTime, i+1);
1728 }
1729 }
1730 }
1731 if (app.conProviders.size() > 0) {
1732 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1733 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1734 updateLruProcessInternalLocked(cpr.app, oomAdj,
1735 updateActivityTime, i+1);
1736 }
1737 }
1738 }
1739
Joe Onorato8a9b2202010-02-26 18:56:32 -08001740 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 if (oomAdj) {
1742 updateOomAdjLocked();
1743 }
1744 }
1745
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001746 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001747 boolean oomAdj, boolean updateActivityTime) {
1748 mLruSeq++;
1749 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1750 }
1751
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001752 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 String processName, int uid) {
1754 if (uid == Process.SYSTEM_UID) {
1755 // The system gets to run in any process. If there are multiple
1756 // processes with the same uid, just pick the first (this
1757 // should never happen).
1758 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1759 processName);
1760 return procs != null ? procs.valueAt(0) : null;
1761 }
1762 ProcessRecord proc = mProcessNames.get(processName, uid);
1763 return proc;
1764 }
1765
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001766 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001767 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001768 try {
1769 if (pm.performDexOpt(packageName)) {
1770 mDidDexOpt = true;
1771 }
1772 } catch (RemoteException e) {
1773 }
1774 }
1775
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001776 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 int transit = mWindowManager.getPendingAppTransition();
1778 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1779 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1780 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1781 }
1782
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001783 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001785 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1787 // We don't have to do anything more if:
1788 // (1) There is an existing application record; and
1789 // (2) The caller doesn't think it is dead, OR there is no thread
1790 // object attached to it so we know it couldn't have crashed; and
1791 // (3) There is a pid assigned to it, so it is either starting or
1792 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001793 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 + " app=" + app + " knownToBeDead=" + knownToBeDead
1795 + " thread=" + (app != null ? app.thread : null)
1796 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001797 if (app != null && app.pid > 0) {
1798 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001799 // We already have the app running, or are waiting for it to
1800 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001801 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001802 return app;
1803 } else {
1804 // An application record is attached to a previous process,
1805 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001806 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001807 handleAppDiedLocked(app, true);
1808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 String hostingNameStr = hostingName != null
1812 ? hostingName.flattenToShortString() : null;
1813
1814 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1815 // If we are in the background, then check to see if this process
1816 // is bad. If so, we will just silently fail.
1817 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001818 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1819 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 return null;
1821 }
1822 } else {
1823 // When the user is explicitly starting a process, then clear its
1824 // crash count so that we won't make it bad until they see at
1825 // least one crash dialog again, and make the process good again
1826 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001827 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1828 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 mProcessCrashTimes.remove(info.processName, info.uid);
1830 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001831 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 info.processName);
1833 mBadProcesses.remove(info.processName, info.uid);
1834 if (app != null) {
1835 app.bad = false;
1836 }
1837 }
1838 }
1839
1840 if (app == null) {
1841 app = newProcessRecordLocked(null, info, processName);
1842 mProcessNames.put(processName, info.uid, app);
1843 } else {
1844 // If this is a new package in the process, add the package to the list
1845 app.addPackage(info.packageName);
1846 }
1847
1848 // If the system is not ready yet, then hold off on starting this
1849 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001850 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001851 && !isAllowedWhileBooting(info)
1852 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 if (!mProcessesOnHold.contains(app)) {
1854 mProcessesOnHold.add(app);
1855 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001856 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 return app;
1858 }
1859
1860 startProcessLocked(app, hostingType, hostingNameStr);
1861 return (app.pid != 0) ? app : null;
1862 }
1863
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001864 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1865 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1866 }
1867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 private final void startProcessLocked(ProcessRecord app,
1869 String hostingType, String hostingNameStr) {
1870 if (app.pid > 0 && app.pid != MY_PID) {
1871 synchronized (mPidsSelfLocked) {
1872 mPidsSelfLocked.remove(app.pid);
1873 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1874 }
1875 app.pid = 0;
1876 }
1877
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001878 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1879 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001880 mProcessesOnHold.remove(app);
1881
1882 updateCpuStats();
1883
1884 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1885 mProcDeaths[0] = 0;
1886
1887 try {
1888 int uid = app.info.uid;
1889 int[] gids = null;
1890 try {
1891 gids = mContext.getPackageManager().getPackageGids(
1892 app.info.packageName);
1893 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001894 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 }
1896 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1897 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1898 && mTopComponent != null
1899 && app.processName.equals(mTopComponent.getPackageName())) {
1900 uid = 0;
1901 }
1902 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1903 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1904 uid = 0;
1905 }
1906 }
1907 int debugFlags = 0;
1908 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1909 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1910 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001911 // Run the app in safe mode if its manifest requests so or the
1912 // system is booted in safe mode.
1913 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1914 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001915 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1918 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1919 }
1920 if ("1".equals(SystemProperties.get("debug.assert"))) {
1921 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1922 }
1923 int pid = Process.start("android.app.ActivityThread",
1924 mSimpleProcessManagement ? app.processName : null, uid, uid,
1925 gids, debugFlags, null);
1926 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1927 synchronized (bs) {
1928 if (bs.isOnBattery()) {
1929 app.batteryStats.incStartsLocked();
1930 }
1931 }
1932
Doug Zongker2bec3d42009-12-04 12:52:44 -08001933 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 app.processName, hostingType,
1935 hostingNameStr != null ? hostingNameStr : "");
1936
1937 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001938 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 }
1940
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001941 StringBuilder buf = mStringBuilder;
1942 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 buf.append("Start proc ");
1944 buf.append(app.processName);
1945 buf.append(" for ");
1946 buf.append(hostingType);
1947 if (hostingNameStr != null) {
1948 buf.append(" ");
1949 buf.append(hostingNameStr);
1950 }
1951 buf.append(": pid=");
1952 buf.append(pid);
1953 buf.append(" uid=");
1954 buf.append(uid);
1955 buf.append(" gids={");
1956 if (gids != null) {
1957 for (int gi=0; gi<gids.length; gi++) {
1958 if (gi != 0) buf.append(", ");
1959 buf.append(gids[gi]);
1960
1961 }
1962 }
1963 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001964 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 if (pid == 0 || pid == MY_PID) {
1966 // Processes are being emulated with threads.
1967 app.pid = MY_PID;
1968 app.removed = false;
1969 mStartingProcesses.add(app);
1970 } else if (pid > 0) {
1971 app.pid = pid;
1972 app.removed = false;
1973 synchronized (mPidsSelfLocked) {
1974 this.mPidsSelfLocked.put(pid, app);
1975 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1976 msg.obj = app;
1977 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1978 }
1979 } else {
1980 app.pid = 0;
1981 RuntimeException e = new RuntimeException(
1982 "Failure starting process " + app.processName
1983 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001984 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 }
1986 } catch (RuntimeException e) {
1987 // XXX do better error recovery.
1988 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001989 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 }
1991 }
1992
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001993 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001994 if (resumed) {
1995 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1996 } else {
1997 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1998 }
1999 }
2000
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002001 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002002 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2003 && mTopAction == null) {
2004 // We are running in factory test mode, but unable to find
2005 // the factory test app, so just sit around displaying the
2006 // error message and don't try to start anything.
2007 return false;
2008 }
2009 Intent intent = new Intent(
2010 mTopAction,
2011 mTopData != null ? Uri.parse(mTopData) : null);
2012 intent.setComponent(mTopComponent);
2013 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2014 intent.addCategory(Intent.CATEGORY_HOME);
2015 }
2016 ActivityInfo aInfo =
2017 intent.resolveActivityInfo(mContext.getPackageManager(),
2018 STOCK_PM_FLAGS);
2019 if (aInfo != null) {
2020 intent.setComponent(new ComponentName(
2021 aInfo.applicationInfo.packageName, aInfo.name));
2022 // Don't do this if the home app is currently being
2023 // instrumented.
2024 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2025 aInfo.applicationInfo.uid);
2026 if (app == null || app.instrumentationClass == null) {
2027 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002028 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002029 null, null, 0, 0, 0, false, false);
2030 }
2031 }
2032
2033
2034 return true;
2035 }
2036
2037 /**
2038 * Starts the "new version setup screen" if appropriate.
2039 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002040 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002041 // Only do this once per boot.
2042 if (mCheckedForSetup) {
2043 return;
2044 }
2045
2046 // We will show this screen if the current one is a different
2047 // version than the last one shown, and we are not running in
2048 // low-level factory test mode.
2049 final ContentResolver resolver = mContext.getContentResolver();
2050 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2051 Settings.Secure.getInt(resolver,
2052 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2053 mCheckedForSetup = true;
2054
2055 // See if we should be showing the platform update setup UI.
2056 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2057 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2058 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2059
2060 // We don't allow third party apps to replace this.
2061 ResolveInfo ri = null;
2062 for (int i=0; ris != null && i<ris.size(); i++) {
2063 if ((ris.get(i).activityInfo.applicationInfo.flags
2064 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2065 ri = ris.get(i);
2066 break;
2067 }
2068 }
2069
2070 if (ri != null) {
2071 String vers = ri.activityInfo.metaData != null
2072 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2073 : null;
2074 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2075 vers = ri.activityInfo.applicationInfo.metaData.getString(
2076 Intent.METADATA_SETUP_VERSION);
2077 }
2078 String lastVers = Settings.Secure.getString(
2079 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2080 if (vers != null && !vers.equals(lastVers)) {
2081 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2082 intent.setComponent(new ComponentName(
2083 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002084 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002085 null, null, 0, 0, 0, false, false);
2086 }
2087 }
2088 }
2089 }
2090
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002091 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002092 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002093
2094 final int identHash = System.identityHashCode(r);
2095 updateUsageStats(r, true);
2096
2097 int i = mWatchers.beginBroadcast();
2098 while (i > 0) {
2099 i--;
2100 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2101 if (w != null) {
2102 try {
2103 w.activityResuming(identHash);
2104 } catch (RemoteException e) {
2105 }
2106 }
2107 }
2108 mWatchers.finishBroadcast();
2109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002111 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002112 final int N = mPendingActivityLaunches.size();
2113 if (N <= 0) {
2114 return;
2115 }
2116 for (int i=0; i<N; i++) {
2117 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002118 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002119 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2120 doResume && i == (N-1));
2121 }
2122 mPendingActivityLaunches.clear();
2123 }
2124
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002125 public final int startActivity(IApplicationThread caller,
2126 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2127 int grantedMode, IBinder resultTo,
2128 String resultWho, int requestCode, boolean onlyIfNeeded,
2129 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002130 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002131 grantedUriPermissions, grantedMode, resultTo, resultWho,
2132 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002133 }
2134
2135 public final WaitResult startActivityAndWait(IApplicationThread caller,
2136 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2137 int grantedMode, IBinder resultTo,
2138 String resultWho, int requestCode, boolean onlyIfNeeded,
2139 boolean debug) {
2140 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002141 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002142 grantedUriPermissions, grantedMode, resultTo, resultWho,
2143 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002144 return res;
2145 }
2146
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002147 public final int startActivityWithConfig(IApplicationThread caller,
2148 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2149 int grantedMode, IBinder resultTo,
2150 String resultWho, int requestCode, boolean onlyIfNeeded,
2151 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002152 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002153 grantedUriPermissions, grantedMode, resultTo, resultWho,
2154 requestCode, onlyIfNeeded, debug, null, config);
2155 }
2156
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002157 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002158 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002159 IBinder resultTo, String resultWho, int requestCode,
2160 int flagsMask, int flagsValues) {
2161 // Refuse possible leaked file descriptors
2162 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2163 throw new IllegalArgumentException("File descriptors passed in Intent");
2164 }
2165
2166 IIntentSender sender = intent.getTarget();
2167 if (!(sender instanceof PendingIntentRecord)) {
2168 throw new IllegalArgumentException("Bad PendingIntent object");
2169 }
2170
2171 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002172
2173 synchronized (this) {
2174 // If this is coming from the currently resumed activity, it is
2175 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002176 if (mMainStack.mResumedActivity != null
2177 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002178 Binder.getCallingUid()) {
2179 mAppSwitchesAllowedTime = 0;
2180 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002181 }
2182
2183 return pir.sendInner(0, fillInIntent, resolvedType,
2184 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2185 }
2186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187 public boolean startNextMatchingActivity(IBinder callingActivity,
2188 Intent intent) {
2189 // Refuse possible leaked file descriptors
2190 if (intent != null && intent.hasFileDescriptors() == true) {
2191 throw new IllegalArgumentException("File descriptors passed in Intent");
2192 }
2193
2194 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002195 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 if (index < 0) {
2197 return false;
2198 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002199 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 if (r.app == null || r.app.thread == null) {
2201 // The caller is not running... d'oh!
2202 return false;
2203 }
2204 intent = new Intent(intent);
2205 // The caller is not allowed to change the data.
2206 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2207 // And we are resetting to find the next component...
2208 intent.setComponent(null);
2209
2210 ActivityInfo aInfo = null;
2211 try {
2212 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002213 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002215 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216
2217 // Look for the original activity in the list...
2218 final int N = resolves != null ? resolves.size() : 0;
2219 for (int i=0; i<N; i++) {
2220 ResolveInfo rInfo = resolves.get(i);
2221 if (rInfo.activityInfo.packageName.equals(r.packageName)
2222 && rInfo.activityInfo.name.equals(r.info.name)) {
2223 // We found the current one... the next matching is
2224 // after it.
2225 i++;
2226 if (i<N) {
2227 aInfo = resolves.get(i).activityInfo;
2228 }
2229 break;
2230 }
2231 }
2232 } catch (RemoteException e) {
2233 }
2234
2235 if (aInfo == null) {
2236 // Nobody who is next!
2237 return false;
2238 }
2239
2240 intent.setComponent(new ComponentName(
2241 aInfo.applicationInfo.packageName, aInfo.name));
2242 intent.setFlags(intent.getFlags()&~(
2243 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2244 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2245 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2246 Intent.FLAG_ACTIVITY_NEW_TASK));
2247
2248 // Okay now we need to start the new activity, replacing the
2249 // currently running activity. This is a little tricky because
2250 // we want to start the new one as if the current one is finished,
2251 // but not finish the current one first so that there is no flicker.
2252 // And thus...
2253 final boolean wasFinishing = r.finishing;
2254 r.finishing = true;
2255
2256 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002257 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 final String resultWho = r.resultWho;
2259 final int requestCode = r.requestCode;
2260 r.resultTo = null;
2261 if (resultTo != null) {
2262 resultTo.removeResultsLocked(r, resultWho, requestCode);
2263 }
2264
2265 final long origId = Binder.clearCallingIdentity();
2266 // XXX we are not dealing with propagating grantedUriPermissions...
2267 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002268 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002270 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 Binder.restoreCallingIdentity(origId);
2272
2273 r.finishing = wasFinishing;
2274 if (res != START_SUCCESS) {
2275 return false;
2276 }
2277 return true;
2278 }
2279 }
2280
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002281 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 Intent intent, String resolvedType, IBinder resultTo,
2283 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002284
2285 // This is so super not safe, that only the system (or okay root)
2286 // can do it.
2287 final int callingUid = Binder.getCallingUid();
2288 if (callingUid != 0 && callingUid != Process.myUid()) {
2289 throw new SecurityException(
2290 "startActivityInPackage only available to the system");
2291 }
2292
The Android Open Source Project4df24232009-03-05 14:34:35 -08002293 final boolean componentSpecified = intent.getComponent() != null;
2294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 // Don't modify the client's object!
2296 intent = new Intent(intent);
2297
2298 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002299 ActivityInfo aInfo;
2300 try {
2301 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002302 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002303 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002304 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 aInfo = rInfo != null ? rInfo.activityInfo : null;
2306 } catch (RemoteException e) {
2307 aInfo = null;
2308 }
2309
2310 if (aInfo != null) {
2311 // Store the found target back into the intent, because now that
2312 // we have it we never want to do this again. For example, if the
2313 // user navigates back to this point in the history, we should
2314 // always restart the exact same activity.
2315 intent.setComponent(new ComponentName(
2316 aInfo.applicationInfo.packageName, aInfo.name));
2317 }
2318
2319 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002320 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002321 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002322 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 }
2324 }
2325
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002326 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002327 // Remove any existing entries that are the same kind of task.
2328 int N = mRecentTasks.size();
2329 for (int i=0; i<N; i++) {
2330 TaskRecord tr = mRecentTasks.get(i);
2331 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2332 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2333 mRecentTasks.remove(i);
2334 i--;
2335 N--;
2336 if (task.intent == null) {
2337 // If the new recent task we are adding is not fully
2338 // specified, then replace it with the existing recent task.
2339 task = tr;
2340 }
2341 }
2342 }
2343 if (N >= MAX_RECENT_TASKS) {
2344 mRecentTasks.remove(N-1);
2345 }
2346 mRecentTasks.add(0, task);
2347 }
2348
2349 public void setRequestedOrientation(IBinder token,
2350 int requestedOrientation) {
2351 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002352 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353 if (index < 0) {
2354 return;
2355 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002356 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002357 final long origId = Binder.clearCallingIdentity();
2358 mWindowManager.setAppOrientation(r, requestedOrientation);
2359 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002360 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 r.mayFreezeScreenLocked(r.app) ? r : null);
2362 if (config != null) {
2363 r.frozenBeforeDestroy = true;
2364 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002365 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002366 }
2367 }
2368 Binder.restoreCallingIdentity(origId);
2369 }
2370 }
2371
2372 public int getRequestedOrientation(IBinder token) {
2373 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002374 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375 if (index < 0) {
2376 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2377 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002378 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 return mWindowManager.getAppOrientation(r);
2380 }
2381 }
2382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383 /**
2384 * This is the internal entry point for handling Activity.finish().
2385 *
2386 * @param token The Binder token referencing the Activity we want to finish.
2387 * @param resultCode Result code, if any, from this Activity.
2388 * @param resultData Result data (Intent), if any, from this Activity.
2389 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002390 * @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 -08002391 */
2392 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2393 // Refuse possible leaked file descriptors
2394 if (resultData != null && resultData.hasFileDescriptors() == true) {
2395 throw new IllegalArgumentException("File descriptors passed in Intent");
2396 }
2397
2398 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002399 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002400 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002401 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 if (next != null) {
2403 // ask watcher if this is allowed
2404 boolean resumeOK = true;
2405 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002406 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002407 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002408 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002409 }
2410
2411 if (!resumeOK) {
2412 return false;
2413 }
2414 }
2415 }
2416 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002417 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002418 resultData, "app-request");
2419 Binder.restoreCallingIdentity(origId);
2420 return res;
2421 }
2422 }
2423
Dianne Hackborn860755f2010-06-03 18:47:52 -07002424 public final void finishHeavyWeightApp() {
2425 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2426 != PackageManager.PERMISSION_GRANTED) {
2427 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2428 + Binder.getCallingPid()
2429 + ", uid=" + Binder.getCallingUid()
2430 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2431 Slog.w(TAG, msg);
2432 throw new SecurityException(msg);
2433 }
2434
2435 synchronized(this) {
2436 if (mHeavyWeightProcess == null) {
2437 return;
2438 }
2439
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002440 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002441 mHeavyWeightProcess.activities);
2442 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002443 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002444 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002445 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002446 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002447 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002448 null, "finish-heavy");
2449 }
2450 }
2451 }
2452
2453 mHeavyWeightProcess = null;
2454 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2455 }
2456 }
2457
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002458 public void crashApplication(int uid, int initialPid, String packageName,
2459 String message) {
2460 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2461 != PackageManager.PERMISSION_GRANTED) {
2462 String msg = "Permission Denial: crashApplication() from pid="
2463 + Binder.getCallingPid()
2464 + ", uid=" + Binder.getCallingUid()
2465 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2466 Slog.w(TAG, msg);
2467 throw new SecurityException(msg);
2468 }
2469
2470 synchronized(this) {
2471 ProcessRecord proc = null;
2472
2473 // Figure out which process to kill. We don't trust that initialPid
2474 // still has any relation to current pids, so must scan through the
2475 // list.
2476 synchronized (mPidsSelfLocked) {
2477 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2478 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2479 if (p.info.uid != uid) {
2480 continue;
2481 }
2482 if (p.pid == initialPid) {
2483 proc = p;
2484 break;
2485 }
2486 for (String str : p.pkgList) {
2487 if (str.equals(packageName)) {
2488 proc = p;
2489 }
2490 }
2491 }
2492 }
2493
2494 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002495 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002496 + " initialPid=" + initialPid
2497 + " packageName=" + packageName);
2498 return;
2499 }
2500
2501 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002502 if (proc.pid == Process.myPid()) {
2503 Log.w(TAG, "crashApplication: trying to crash self!");
2504 return;
2505 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002506 long ident = Binder.clearCallingIdentity();
2507 try {
2508 proc.thread.scheduleCrash(message);
2509 } catch (RemoteException e) {
2510 }
2511 Binder.restoreCallingIdentity(ident);
2512 }
2513 }
2514 }
2515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 public final void finishSubActivity(IBinder token, String resultWho,
2517 int requestCode) {
2518 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002519 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002520 if (index < 0) {
2521 return;
2522 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002523 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524
2525 final long origId = Binder.clearCallingIdentity();
2526
2527 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002528 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2529 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002530 if (r.resultTo == self && r.requestCode == requestCode) {
2531 if ((r.resultWho == null && resultWho == null) ||
2532 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002533 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002534 Activity.RESULT_CANCELED, null, "request-sub");
2535 }
2536 }
2537 }
2538
2539 Binder.restoreCallingIdentity(origId);
2540 }
2541 }
2542
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002543 public boolean willActivityBeVisible(IBinder token) {
2544 synchronized(this) {
2545 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002546 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2547 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002548 if (r == token) {
2549 return true;
2550 }
2551 if (r.fullscreen && !r.finishing) {
2552 return false;
2553 }
2554 }
2555 return true;
2556 }
2557 }
2558
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002559 public void overridePendingTransition(IBinder token, String packageName,
2560 int enterAnim, int exitAnim) {
2561 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002562 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002563 if (index < 0) {
2564 return;
2565 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002566 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002567
2568 final long origId = Binder.clearCallingIdentity();
2569
2570 if (self.state == ActivityState.RESUMED
2571 || self.state == ActivityState.PAUSING) {
2572 mWindowManager.overridePendingAppTransition(packageName,
2573 enterAnim, exitAnim);
2574 }
2575
2576 Binder.restoreCallingIdentity(origId);
2577 }
2578 }
2579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581 * Main function for removing an existing process from the activity manager
2582 * as a result of that process going away. Clears out all connections
2583 * to the process.
2584 */
2585 private final void handleAppDiedLocked(ProcessRecord app,
2586 boolean restarting) {
2587 cleanUpApplicationRecordLocked(app, restarting, -1);
2588 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002589 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 }
2591
2592 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002593 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2594 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2595 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002597 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2598 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 }
2600
2601 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002602 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002603
2604 boolean atTop = true;
2605 boolean hasVisibleActivities = false;
2606
2607 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002608 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002609 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 TAG, "Removing app " + app + " from history with " + i + " entries");
2611 while (i > 0) {
2612 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002613 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002614 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2616 if (r.app == app) {
2617 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002618 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619 TAG, "Removing this entry! frozen=" + r.haveState
2620 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002621 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622
2623 r.inHistory = false;
2624 mWindowManager.removeAppToken(r);
2625 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002626 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002627 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002628 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629
2630 } else {
2631 // We have the current state for this activity, so
2632 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002633 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 TAG, "Keeping entry, setting app to null");
2635 if (r.visible) {
2636 hasVisibleActivities = true;
2637 }
2638 r.app = null;
2639 r.nowVisible = false;
2640 if (!r.haveState) {
2641 r.icicle = null;
2642 }
2643 }
2644
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002645 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002646 r.state = ActivityState.STOPPED;
2647 }
2648 atTop = false;
2649 }
2650
2651 app.activities.clear();
2652
2653 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002654 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655 + " running instrumentation " + app.instrumentationClass);
2656 Bundle info = new Bundle();
2657 info.putString("shortMsg", "Process crashed.");
2658 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2659 }
2660
2661 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002662 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002663 // If there was nothing to resume, and we are not already
2664 // restarting this process, but there is a visible activity that
2665 // is hosted by the process... then make sure all visible
2666 // activities are running, taking care of restarting this
2667 // process.
2668 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002669 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002670 }
2671 }
2672 }
2673 }
2674
2675 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2676 IBinder threadBinder = thread.asBinder();
2677
2678 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002679 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2680 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2682 return i;
2683 }
2684 }
2685 return -1;
2686 }
2687
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002688 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 IApplicationThread thread) {
2690 if (thread == null) {
2691 return null;
2692 }
2693
2694 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002695 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 }
2697
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002698 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 IApplicationThread thread) {
2700
2701 mProcDeaths[0]++;
2702
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002703 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2704 synchronized (stats) {
2705 stats.noteProcessDiedLocked(app.info.uid, pid);
2706 }
2707
Magnus Edlund7bb25812010-02-24 15:45:06 +01002708 // Clean up already done if the process has been re-started.
2709 if (app.pid == pid && app.thread != null &&
2710 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002711 if (!app.killedBackground) {
2712 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2713 + ") has died.");
2714 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002715 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002716 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 TAG, "Dying app: " + app + ", pid: " + pid
2718 + ", thread: " + thread.asBinder());
2719 boolean doLowMem = app.instrumentationClass == null;
2720 handleAppDiedLocked(app, false);
2721
2722 if (doLowMem) {
2723 // If there are no longer any background processes running,
2724 // and the app that died was not running instrumentation,
2725 // then tell everyone we are now low on memory.
2726 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002727 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2728 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002729 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2730 haveBg = true;
2731 break;
2732 }
2733 }
2734
2735 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002736 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002737 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002738 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002739 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2740 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002741 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002742 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2743 // The low memory report is overriding any current
2744 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002745 // heavy/important/visible/foreground processes first.
2746 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002747 rec.lastRequestedGc = 0;
2748 } else {
2749 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002751 rec.reportLowMemory = true;
2752 rec.lastLowMemory = now;
2753 mProcessesToGc.remove(rec);
2754 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 }
2756 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002757 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002758 }
2759 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002760 } else if (app.pid != pid) {
2761 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002762 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002763 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002764 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002765 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002766 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 + thread.asBinder());
2768 }
2769 }
2770
Dan Egnor42471dd2010-01-07 17:25:22 -08002771 /**
2772 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002773 * @param clearTraces causes the dump file to be erased prior to the new
2774 * traces being written, if true; when false, the new traces will be
2775 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002776 * @param firstPids of dalvik VM processes to dump stack traces for first
2777 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002778 * @return file containing stack traces, or null if no dump file is configured
2779 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002780 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2781 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002782 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2783 if (tracesPath == null || tracesPath.length() == 0) {
2784 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002785 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002786
2787 File tracesFile = new File(tracesPath);
2788 try {
2789 File tracesDir = tracesFile.getParentFile();
2790 if (!tracesDir.exists()) tracesFile.mkdirs();
2791 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2792
Christopher Tate6ee412d2010-05-28 12:01:56 -07002793 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002794 tracesFile.createNewFile();
2795 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2796 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002797 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002798 return null;
2799 }
2800
2801 // Use a FileObserver to detect when traces finish writing.
2802 // The order of traces is considered important to maintain for legibility.
2803 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2804 public synchronized void onEvent(int event, String path) { notify(); }
2805 };
2806
2807 try {
2808 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002809
2810 // First collect all of the stacks of the most important pids.
2811 try {
2812 int num = firstPids.size();
2813 for (int i = 0; i < num; i++) {
2814 synchronized (observer) {
2815 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2816 observer.wait(200); // Wait for write-close, give up after 200msec
2817 }
2818 }
2819 } catch (InterruptedException e) {
2820 Log.wtf(TAG, e);
2821 }
2822
2823 // Next measure CPU usage.
2824 if (processStats != null) {
2825 processStats.init();
2826 System.gc();
2827 processStats.update();
2828 try {
2829 synchronized (processStats) {
2830 processStats.wait(500); // measure over 1/2 second.
2831 }
2832 } catch (InterruptedException e) {
2833 }
2834 processStats.update();
2835
2836 // We'll take the stack crawls of just the top apps using CPU.
2837 final int N = processStats.countWorkingStats();
2838 int numProcs = 0;
2839 for (int i=0; i<N && numProcs<5; i++) {
2840 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2841 if (lastPids.indexOfKey(stats.pid) >= 0) {
2842 numProcs++;
2843 try {
2844 synchronized (observer) {
2845 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2846 observer.wait(200); // Wait for write-close, give up after 200msec
2847 }
2848 } catch (InterruptedException e) {
2849 Log.wtf(TAG, e);
2850 }
2851
2852 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002853 }
2854 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002855
2856 return tracesFile;
2857
Dan Egnor42471dd2010-01-07 17:25:22 -08002858 } finally {
2859 observer.stopWatching();
2860 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002861 }
2862
Jeff Brown4d94a762010-09-23 11:33:28 -07002863 private final class AppNotResponding implements Runnable {
2864 private final ProcessRecord mApp;
2865 private final String mAnnotation;
2866
2867 public AppNotResponding(ProcessRecord app, String annotation) {
2868 mApp = app;
2869 mAnnotation = annotation;
2870 }
2871
2872 @Override
2873 public void run() {
2874 appNotResponding(mApp, null, null, mAnnotation);
2875 }
2876 }
2877
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002878 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2879 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002880 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2881 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2882
Dianne Hackborn287952c2010-09-22 22:34:31 -07002883 if (mController != null) {
2884 try {
2885 // 0 == continue, -1 = kill process immediately
2886 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2887 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2888 } catch (RemoteException e) {
2889 mController = null;
2890 }
2891 }
2892
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002893 long anrTime = SystemClock.uptimeMillis();
2894 if (MONITOR_CPU_USAGE) {
2895 updateCpuStatsNow();
2896 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002897
2898 synchronized (this) {
2899 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2900 if (mShuttingDown) {
2901 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2902 return;
2903 } else if (app.notResponding) {
2904 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2905 return;
2906 } else if (app.crashing) {
2907 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2908 return;
2909 }
2910
2911 // In case we come through here for the same app before completing
2912 // this one, mark as anring now so we will bail out.
2913 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002914
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002915 // Log the ANR to the event log.
2916 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2917 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002918
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002919 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002920 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002921
2922 int parentPid = app.pid;
2923 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002924 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002925
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002926 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002927
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002928 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2929 ProcessRecord r = mLruProcesses.get(i);
2930 if (r != null && r.thread != null) {
2931 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002932 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2933 if (r.persistent) {
2934 firstPids.add(pid);
2935 } else {
2936 lastPids.put(pid, Boolean.TRUE);
2937 }
2938 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940 }
2941 }
2942
Dan Egnor42471dd2010-01-07 17:25:22 -08002943 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002944 StringBuilder info = mStringBuilder;
2945 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002946 info.append("ANR in ").append(app.processName);
2947 if (activity != null && activity.shortComponentName != null) {
2948 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002949 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002950 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002952 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002954 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002955 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002957
Dianne Hackborn287952c2010-09-22 22:34:31 -07002958 final ProcessStats processStats = new ProcessStats(true);
2959
2960 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2961
Dan Egnor42471dd2010-01-07 17:25:22 -08002962 String cpuInfo = null;
2963 if (MONITOR_CPU_USAGE) {
2964 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002965 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002966 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002967 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002968 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002969 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 }
2971
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002972 info.append(processStats.printCurrentState(anrTime));
2973
Joe Onorato8a9b2202010-02-26 18:56:32 -08002974 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002975 if (tracesFile == null) {
2976 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2977 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2978 }
2979
2980 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2981
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002982 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002983 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002984 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2985 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002987 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2988 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 }
2990 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002991 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002992 }
2993 }
2994
Dan Egnor42471dd2010-01-07 17:25:22 -08002995 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2996 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2997 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002998
2999 synchronized (this) {
3000 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
3001 Process.killProcess(app.pid);
3002 return;
3003 }
3004
3005 // Set the app's notResponding state, and look up the errorReportReceiver
3006 makeAppNotRespondingLocked(app,
3007 activity != null ? activity.shortComponentName : null,
3008 annotation != null ? "ANR " + annotation : "ANR",
3009 info.toString());
3010
3011 // Bring up the infamous App Not Responding dialog
3012 Message msg = Message.obtain();
3013 HashMap map = new HashMap();
3014 msg.what = SHOW_NOT_RESPONDING_MSG;
3015 msg.obj = map;
3016 map.put("app", app);
3017 if (activity != null) {
3018 map.put("activity", activity);
3019 }
3020
3021 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003022 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 }
3024
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003025 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3026 if (!mLaunchWarningShown) {
3027 mLaunchWarningShown = true;
3028 mHandler.post(new Runnable() {
3029 @Override
3030 public void run() {
3031 synchronized (ActivityManagerService.this) {
3032 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3033 d.show();
3034 mHandler.postDelayed(new Runnable() {
3035 @Override
3036 public void run() {
3037 synchronized (ActivityManagerService.this) {
3038 d.dismiss();
3039 mLaunchWarningShown = false;
3040 }
3041 }
3042 }, 4000);
3043 }
3044 }
3045 });
3046 }
3047 }
3048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 public boolean clearApplicationUserData(final String packageName,
3050 final IPackageDataObserver observer) {
3051 int uid = Binder.getCallingUid();
3052 int pid = Binder.getCallingPid();
3053 long callingId = Binder.clearCallingIdentity();
3054 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003055 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003056 int pkgUid = -1;
3057 synchronized(this) {
3058 try {
3059 pkgUid = pm.getPackageUid(packageName);
3060 } catch (RemoteException e) {
3061 }
3062 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003063 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003064 return false;
3065 }
3066 if (uid == pkgUid || checkComponentPermission(
3067 android.Manifest.permission.CLEAR_APP_USER_DATA,
3068 pid, uid, -1)
3069 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003070 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003071 } else {
3072 throw new SecurityException(pid+" does not have permission:"+
3073 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3074 "for process:"+packageName);
3075 }
3076 }
3077
3078 try {
3079 //clear application user data
3080 pm.clearApplicationUserData(packageName, observer);
3081 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3082 Uri.fromParts("package", packageName, null));
3083 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003084 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3085 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 } catch (RemoteException e) {
3087 }
3088 } finally {
3089 Binder.restoreCallingIdentity(callingId);
3090 }
3091 return true;
3092 }
3093
Dianne Hackborn03abb812010-01-04 18:43:19 -08003094 public void killBackgroundProcesses(final String packageName) {
3095 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3096 != PackageManager.PERMISSION_GRANTED &&
3097 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3098 != PackageManager.PERMISSION_GRANTED) {
3099 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 + Binder.getCallingPid()
3101 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003102 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003103 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003104 throw new SecurityException(msg);
3105 }
3106
3107 long callingId = Binder.clearCallingIdentity();
3108 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003109 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 int pkgUid = -1;
3111 synchronized(this) {
3112 try {
3113 pkgUid = pm.getPackageUid(packageName);
3114 } catch (RemoteException e) {
3115 }
3116 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003117 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003118 return;
3119 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003120 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003121 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003122 }
3123 } finally {
3124 Binder.restoreCallingIdentity(callingId);
3125 }
3126 }
3127
3128 public void forceStopPackage(final String packageName) {
3129 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3130 != PackageManager.PERMISSION_GRANTED) {
3131 String msg = "Permission Denial: forceStopPackage() from pid="
3132 + Binder.getCallingPid()
3133 + ", uid=" + Binder.getCallingUid()
3134 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003135 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003136 throw new SecurityException(msg);
3137 }
3138
3139 long callingId = Binder.clearCallingIdentity();
3140 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003141 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003142 int pkgUid = -1;
3143 synchronized(this) {
3144 try {
3145 pkgUid = pm.getPackageUid(packageName);
3146 } catch (RemoteException e) {
3147 }
3148 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003149 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003150 return;
3151 }
3152 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003153 }
3154 } finally {
3155 Binder.restoreCallingIdentity(callingId);
3156 }
3157 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003158
3159 /*
3160 * The pkg name and uid have to be specified.
3161 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3162 */
3163 public void killApplicationWithUid(String pkg, int uid) {
3164 if (pkg == null) {
3165 return;
3166 }
3167 // Make sure the uid is valid.
3168 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003169 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003170 return;
3171 }
3172 int callerUid = Binder.getCallingUid();
3173 // Only the system server can kill an application
3174 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003175 // Post an aysnc message to kill the application
3176 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3177 msg.arg1 = uid;
3178 msg.arg2 = 0;
3179 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003180 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003181 } else {
3182 throw new SecurityException(callerUid + " cannot kill pkg: " +
3183 pkg);
3184 }
3185 }
3186
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003187 public void closeSystemDialogs(String reason) {
3188 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003189 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003190 if (reason != null) {
3191 intent.putExtra("reason", reason);
3192 }
3193
3194 final int uid = Binder.getCallingUid();
3195 final long origId = Binder.clearCallingIdentity();
3196 synchronized (this) {
3197 int i = mWatchers.beginBroadcast();
3198 while (i > 0) {
3199 i--;
3200 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3201 if (w != null) {
3202 try {
3203 w.closingSystemDialogs(reason);
3204 } catch (RemoteException e) {
3205 }
3206 }
3207 }
3208 mWatchers.finishBroadcast();
3209
Dianne Hackbornffa42482009-09-23 22:20:11 -07003210 mWindowManager.closeSystemDialogs(reason);
3211
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003212 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3213 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003214 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003215 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003216 Activity.RESULT_CANCELED, null, "close-sys");
3217 }
3218 }
3219
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003220 broadcastIntentLocked(null, null, intent, null,
3221 null, 0, null, null, null, false, false, -1, uid);
3222 }
3223 Binder.restoreCallingIdentity(origId);
3224 }
3225
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003226 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003227 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003228 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3229 for (int i=pids.length-1; i>=0; i--) {
3230 infos[i] = new Debug.MemoryInfo();
3231 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003232 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003233 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003234 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003235
3236 public void killApplicationProcess(String processName, int uid) {
3237 if (processName == null) {
3238 return;
3239 }
3240
3241 int callerUid = Binder.getCallingUid();
3242 // Only the system server can kill an application
3243 if (callerUid == Process.SYSTEM_UID) {
3244 synchronized (this) {
3245 ProcessRecord app = getProcessRecordLocked(processName, uid);
3246 if (app != null) {
3247 try {
3248 app.thread.scheduleSuicide();
3249 } catch (RemoteException e) {
3250 // If the other end already died, then our work here is done.
3251 }
3252 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003253 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003254 + processName + " / " + uid);
3255 }
3256 }
3257 } else {
3258 throw new SecurityException(callerUid + " cannot kill app process: " +
3259 processName);
3260 }
3261 }
3262
Dianne Hackborn03abb812010-01-04 18:43:19 -08003263 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003264 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003265 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3266 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003267 if (!mProcessesReady) {
3268 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 intent.putExtra(Intent.EXTRA_UID, uid);
3271 broadcastIntentLocked(null, null, intent,
3272 null, null, 0, null, null, null,
3273 false, false, MY_PID, Process.SYSTEM_UID);
3274 }
3275
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003276 private final boolean killPackageProcessesLocked(String packageName, int uid,
3277 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003278 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003279
Dianne Hackborn03abb812010-01-04 18:43:19 -08003280 // Remove all processes this package may have touched: all with the
3281 // same UID (except for the system or root user), and all whose name
3282 // matches the package name.
3283 final String procNamePrefix = packageName + ":";
3284 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3285 final int NA = apps.size();
3286 for (int ia=0; ia<NA; ia++) {
3287 ProcessRecord app = apps.valueAt(ia);
3288 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003289 if (doit) {
3290 procs.add(app);
3291 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003292 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3293 || app.processName.equals(packageName)
3294 || app.processName.startsWith(procNamePrefix)) {
3295 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003296 if (!doit) {
3297 return true;
3298 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003299 app.removed = true;
3300 procs.add(app);
3301 }
3302 }
3303 }
3304 }
3305
3306 int N = procs.size();
3307 for (int i=0; i<N; i++) {
3308 removeProcessLocked(procs.get(i), callerWillRestart);
3309 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003310 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003311 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003312
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003313 private final boolean forceStopPackageLocked(String name, int uid,
3314 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 int i, N;
3316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 if (uid < 0) {
3318 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003319 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 } catch (RemoteException e) {
3321 }
3322 }
3323
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003324 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003325 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003326
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003327 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3328 while (badApps.hasNext()) {
3329 SparseArray<Long> ba = badApps.next();
3330 if (ba.get(uid) != null) {
3331 badApps.remove();
3332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003333 }
3334 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003335
3336 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3337 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003338
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003339 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3340 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003342 if (!doit) {
3343 return true;
3344 }
3345 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003346 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 if (r.app != null) {
3348 r.app.removed = true;
3349 }
3350 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003351 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003352 }
3353 }
3354
3355 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3356 for (ServiceRecord service : mServices.values()) {
3357 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003358 if (!doit) {
3359 return true;
3360 }
3361 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003362 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 if (service.app != null) {
3364 service.app.removed = true;
3365 }
3366 service.app = null;
3367 services.add(service);
3368 }
3369 }
3370
3371 N = services.size();
3372 for (i=0; i<N; i++) {
3373 bringDownServiceLocked(services.get(i), true);
3374 }
3375
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003376 if (doit) {
3377 if (purgeCache) {
3378 AttributeCache ac = AttributeCache.instance();
3379 if (ac != null) {
3380 ac.removePackage(name);
3381 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003382 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003383 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003384 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003385
3386 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003387 }
3388
3389 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3390 final String name = app.processName;
3391 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003392 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 TAG, "Force removing process " + app + " (" + name
3394 + "/" + uid + ")");
3395
3396 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003397 if (mHeavyWeightProcess == app) {
3398 mHeavyWeightProcess = null;
3399 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 boolean needRestart = false;
3402 if (app.pid > 0 && app.pid != MY_PID) {
3403 int pid = app.pid;
3404 synchronized (mPidsSelfLocked) {
3405 mPidsSelfLocked.remove(pid);
3406 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3407 }
3408 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003409 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 Process.killProcess(pid);
3411
3412 if (app.persistent) {
3413 if (!callerWillRestart) {
3414 addAppLocked(app.info);
3415 } else {
3416 needRestart = true;
3417 }
3418 }
3419 } else {
3420 mRemovedProcesses.add(app);
3421 }
3422
3423 return needRestart;
3424 }
3425
3426 private final void processStartTimedOutLocked(ProcessRecord app) {
3427 final int pid = app.pid;
3428 boolean gone = false;
3429 synchronized (mPidsSelfLocked) {
3430 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3431 if (knownApp != null && knownApp.thread == null) {
3432 mPidsSelfLocked.remove(pid);
3433 gone = true;
3434 }
3435 }
3436
3437 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003438 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003439 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003440 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003442 if (mHeavyWeightProcess == app) {
3443 mHeavyWeightProcess = null;
3444 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3445 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003446 // Take care of any launching providers waiting for this process.
3447 checkAppInLaunchingProvidersLocked(app, true);
3448 // Take care of any services that are waiting for the process.
3449 for (int i=0; i<mPendingServices.size(); i++) {
3450 ServiceRecord sr = mPendingServices.get(i);
3451 if (app.info.uid == sr.appInfo.uid
3452 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003453 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003454 mPendingServices.remove(i);
3455 i--;
3456 bringDownServiceLocked(sr, true);
3457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003458 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003459 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003460 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003461 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003462 try {
3463 IBackupManager bm = IBackupManager.Stub.asInterface(
3464 ServiceManager.getService(Context.BACKUP_SERVICE));
3465 bm.agentDisconnected(app.info.packageName);
3466 } catch (RemoteException e) {
3467 // Can't happen; the backup manager is local
3468 }
3469 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003470 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003471 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003472 mPendingBroadcast.state = BroadcastRecord.IDLE;
3473 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003474 mPendingBroadcast = null;
3475 scheduleBroadcastsLocked();
3476 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003477 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003478 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 }
3480 }
3481
3482 private final boolean attachApplicationLocked(IApplicationThread thread,
3483 int pid) {
3484
3485 // Find the application record that is being attached... either via
3486 // the pid if we are running in multiple processes, or just pull the
3487 // next app record if we are emulating process with anonymous threads.
3488 ProcessRecord app;
3489 if (pid != MY_PID && pid >= 0) {
3490 synchronized (mPidsSelfLocked) {
3491 app = mPidsSelfLocked.get(pid);
3492 }
3493 } else if (mStartingProcesses.size() > 0) {
3494 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003495 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 } else {
3497 app = null;
3498 }
3499
3500 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003501 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003503 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 if (pid > 0 && pid != MY_PID) {
3505 Process.killProcess(pid);
3506 } else {
3507 try {
3508 thread.scheduleExit();
3509 } catch (Exception e) {
3510 // Ignore exceptions.
3511 }
3512 }
3513 return false;
3514 }
3515
3516 // If this application record is still attached to a previous
3517 // process, clean it up now.
3518 if (app.thread != null) {
3519 handleAppDiedLocked(app, true);
3520 }
3521
3522 // Tell the process all about itself.
3523
Joe Onorato8a9b2202010-02-26 18:56:32 -08003524 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003525 TAG, "Binding process pid " + pid + " to record " + app);
3526
3527 String processName = app.processName;
3528 try {
3529 thread.asBinder().linkToDeath(new AppDeathRecipient(
3530 app, pid, thread), 0);
3531 } catch (RemoteException e) {
3532 app.resetPackageList();
3533 startProcessLocked(app, "link fail", processName);
3534 return false;
3535 }
3536
Doug Zongker2bec3d42009-12-04 12:52:44 -08003537 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538
3539 app.thread = thread;
3540 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003541 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3542 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543 app.forcingToForeground = null;
3544 app.foregroundServices = false;
3545 app.debugging = false;
3546
3547 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3548
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003549 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003550 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003552 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003553 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003554 }
3555
Joe Onorato8a9b2202010-02-26 18:56:32 -08003556 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 TAG, "New app record " + app
3558 + " thread=" + thread.asBinder() + " pid=" + pid);
3559 try {
3560 int testMode = IApplicationThread.DEBUG_OFF;
3561 if (mDebugApp != null && mDebugApp.equals(processName)) {
3562 testMode = mWaitForDebugger
3563 ? IApplicationThread.DEBUG_WAIT
3564 : IApplicationThread.DEBUG_ON;
3565 app.debugging = true;
3566 if (mDebugTransient) {
3567 mDebugApp = mOrigDebugApp;
3568 mWaitForDebugger = mOrigWaitForDebugger;
3569 }
3570 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003571
Christopher Tate181fafa2009-05-14 11:12:14 -07003572 // If the app is being launched for restore or full backup, set it up specially
3573 boolean isRestrictedBackupMode = false;
3574 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3575 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3576 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3577 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003578
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003579 ensurePackageDexOpt(app.instrumentationInfo != null
3580 ? app.instrumentationInfo.packageName
3581 : app.info.packageName);
3582 if (app.instrumentationClass != null) {
3583 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003584 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003585 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003586 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003587 thread.bindApplication(processName, app.instrumentationInfo != null
3588 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 app.instrumentationClass, app.instrumentationProfileFile,
3590 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003591 isRestrictedBackupMode || !normalMode,
3592 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003593 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003594 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003595 } catch (Exception e) {
3596 // todo: Yikes! What should we do? For now we will try to
3597 // start another process, but that could easily get us in
3598 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003599 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600
3601 app.resetPackageList();
3602 startProcessLocked(app, "bind fail", processName);
3603 return false;
3604 }
3605
3606 // Remove this record from the list of starting applications.
3607 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003608 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3609 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 mProcessesOnHold.remove(app);
3611
3612 boolean badApp = false;
3613 boolean didSomething = false;
3614
3615 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003616 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003617 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3619 && processName.equals(hr.processName)) {
3620 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003621 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622 didSomething = true;
3623 }
3624 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003625 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 + hr.intent.getComponent().flattenToShortString(), e);
3627 badApp = true;
3628 }
3629 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003630 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003631 }
3632 }
3633
3634 // Find any services that should be running in this process...
3635 if (!badApp && mPendingServices.size() > 0) {
3636 ServiceRecord sr = null;
3637 try {
3638 for (int i=0; i<mPendingServices.size(); i++) {
3639 sr = mPendingServices.get(i);
3640 if (app.info.uid != sr.appInfo.uid
3641 || !processName.equals(sr.processName)) {
3642 continue;
3643 }
3644
3645 mPendingServices.remove(i);
3646 i--;
3647 realStartServiceLocked(sr, app);
3648 didSomething = true;
3649 }
3650 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003651 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003652 + sr.shortName, e);
3653 badApp = true;
3654 }
3655 }
3656
3657 // Check if the next broadcast receiver is in this process...
3658 BroadcastRecord br = mPendingBroadcast;
3659 if (!badApp && br != null && br.curApp == app) {
3660 try {
3661 mPendingBroadcast = null;
3662 processCurBroadcastLocked(br, app);
3663 didSomething = true;
3664 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003665 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003666 + br.curComponent.flattenToShortString(), e);
3667 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003668 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3670 br.resultExtras, br.resultAbort, true);
3671 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003672 // We need to reset the state if we fails to start the receiver.
3673 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 }
3675 }
3676
Christopher Tate181fafa2009-05-14 11:12:14 -07003677 // Check whether the next backup agent is in this process...
3678 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003679 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003680 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003681 try {
3682 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3683 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003684 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003685 e.printStackTrace();
3686 }
3687 }
3688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 if (badApp) {
3690 // todo: Also need to kill application to deal with all
3691 // kinds of exceptions.
3692 handleAppDiedLocked(app, false);
3693 return false;
3694 }
3695
3696 if (!didSomething) {
3697 updateOomAdjLocked();
3698 }
3699
3700 return true;
3701 }
3702
3703 public final void attachApplication(IApplicationThread thread) {
3704 synchronized (this) {
3705 int callingPid = Binder.getCallingPid();
3706 final long origId = Binder.clearCallingIdentity();
3707 attachApplicationLocked(thread, callingPid);
3708 Binder.restoreCallingIdentity(origId);
3709 }
3710 }
3711
Dianne Hackborne88846e2009-09-30 21:34:25 -07003712 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003714 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003715 Binder.restoreCallingIdentity(origId);
3716 }
3717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003719 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003720 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 mWindowManager.enableScreenAfterBoot();
3722 }
3723
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003724 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003725 IntentFilter pkgFilter = new IntentFilter();
3726 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3727 pkgFilter.addDataScheme("package");
3728 mContext.registerReceiver(new BroadcastReceiver() {
3729 @Override
3730 public void onReceive(Context context, Intent intent) {
3731 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3732 if (pkgs != null) {
3733 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003734 synchronized (ActivityManagerService.this) {
3735 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3736 setResultCode(Activity.RESULT_OK);
3737 return;
3738 }
3739 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003740 }
3741 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003742 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003743 }, pkgFilter);
3744
3745 synchronized (this) {
3746 // Ensure that any processes we had put on hold are now started
3747 // up.
3748 final int NP = mProcessesOnHold.size();
3749 if (NP > 0) {
3750 ArrayList<ProcessRecord> procs =
3751 new ArrayList<ProcessRecord>(mProcessesOnHold);
3752 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003753 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3754 + procs.get(ip));
3755 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003756 }
3757 }
3758
3759 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003760 // Start looking for apps that are abusing wake locks.
3761 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003762 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003763 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003764 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003765 broadcastIntentLocked(null, null,
3766 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3767 null, null, 0, null, null,
3768 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3769 false, false, MY_PID, Process.SYSTEM_UID);
3770 }
3771 }
3772 }
3773
3774 final void ensureBootCompleted() {
3775 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003776 boolean enableScreen;
3777 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003778 booting = mBooting;
3779 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003780 enableScreen = !mBooted;
3781 mBooted = true;
3782 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003783
3784 if (booting) {
3785 finishBooting();
3786 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003787
3788 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003789 enableScreenAfterBoot();
3790 }
3791 }
3792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793 public final void activityPaused(IBinder token, Bundle icicle) {
3794 // Refuse possible leaked file descriptors
3795 if (icicle != null && icicle.hasFileDescriptors()) {
3796 throw new IllegalArgumentException("File descriptors passed in Bundle");
3797 }
3798
3799 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003800 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003801 Binder.restoreCallingIdentity(origId);
3802 }
3803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 public final void activityStopped(IBinder token, Bitmap thumbnail,
3805 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003806 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 TAG, "Activity stopped: token=" + token);
3808
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003809 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810
3811 final long origId = Binder.clearCallingIdentity();
3812
3813 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003814 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003815 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003816 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003817 r.thumbnail = thumbnail;
3818 r.description = description;
3819 r.stopped = true;
3820 r.state = ActivityState.STOPPED;
3821 if (!r.finishing) {
3822 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003823 r.stack.destroyActivityLocked(r, true);
3824 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003825 }
3826 }
3827 }
3828 }
3829
3830 if (r != null) {
3831 sendPendingThumbnail(r, null, null, null, false);
3832 }
3833
3834 trimApplications();
3835
3836 Binder.restoreCallingIdentity(origId);
3837 }
3838
3839 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003840 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003841 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003842 }
3843
3844 public String getCallingPackage(IBinder token) {
3845 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003846 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003847 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003848 }
3849 }
3850
3851 public ComponentName getCallingActivity(IBinder token) {
3852 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003853 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 return r != null ? r.intent.getComponent() : null;
3855 }
3856 }
3857
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003858 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003859 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003861 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 if (r != null) {
3863 return r.resultTo;
3864 }
3865 }
3866 return null;
3867 }
3868
3869 public ComponentName getActivityClassForToken(IBinder token) {
3870 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003871 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003873 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003874 return r.intent.getComponent();
3875 }
3876 return null;
3877 }
3878 }
3879
3880 public String getPackageForToken(IBinder token) {
3881 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003882 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003883 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003884 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003885 return r.packageName;
3886 }
3887 return null;
3888 }
3889 }
3890
3891 public IIntentSender getIntentSender(int type,
3892 String packageName, IBinder token, String resultWho,
3893 int requestCode, Intent intent, String resolvedType, int flags) {
3894 // Refuse possible leaked file descriptors
3895 if (intent != null && intent.hasFileDescriptors() == true) {
3896 throw new IllegalArgumentException("File descriptors passed in Intent");
3897 }
3898
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003899 if (type == INTENT_SENDER_BROADCAST) {
3900 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3901 throw new IllegalArgumentException(
3902 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3903 }
3904 }
3905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906 synchronized(this) {
3907 int callingUid = Binder.getCallingUid();
3908 try {
3909 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3910 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003911 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003912 .getPackageUid(packageName);
3913 if (uid != Binder.getCallingUid()) {
3914 String msg = "Permission Denial: getIntentSender() from pid="
3915 + Binder.getCallingPid()
3916 + ", uid=" + Binder.getCallingUid()
3917 + ", (need uid=" + uid + ")"
3918 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003919 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 throw new SecurityException(msg);
3921 }
3922 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003923
3924 return getIntentSenderLocked(type, packageName, callingUid,
3925 token, resultWho, requestCode, intent, resolvedType, flags);
3926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003927 } catch (RemoteException e) {
3928 throw new SecurityException(e);
3929 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003930 }
3931 }
3932
3933 IIntentSender getIntentSenderLocked(int type,
3934 String packageName, int callingUid, IBinder token, String resultWho,
3935 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003936 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003937 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003938 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003939 if (index < 0) {
3940 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003941 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003942 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003943 if (activity.finishing) {
3944 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003946 }
3947
3948 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3949 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3950 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3951 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3952 |PendingIntent.FLAG_UPDATE_CURRENT);
3953
3954 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3955 type, packageName, activity, resultWho,
3956 requestCode, intent, resolvedType, flags);
3957 WeakReference<PendingIntentRecord> ref;
3958 ref = mIntentSenderRecords.get(key);
3959 PendingIntentRecord rec = ref != null ? ref.get() : null;
3960 if (rec != null) {
3961 if (!cancelCurrent) {
3962 if (updateCurrent) {
3963 rec.key.requestIntent.replaceExtras(intent);
3964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003965 return rec;
3966 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003967 rec.canceled = true;
3968 mIntentSenderRecords.remove(key);
3969 }
3970 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003971 return rec;
3972 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003973 rec = new PendingIntentRecord(this, key, callingUid);
3974 mIntentSenderRecords.put(key, rec.ref);
3975 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3976 if (activity.pendingResults == null) {
3977 activity.pendingResults
3978 = new HashSet<WeakReference<PendingIntentRecord>>();
3979 }
3980 activity.pendingResults.add(rec.ref);
3981 }
3982 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 }
3984
3985 public void cancelIntentSender(IIntentSender sender) {
3986 if (!(sender instanceof PendingIntentRecord)) {
3987 return;
3988 }
3989 synchronized(this) {
3990 PendingIntentRecord rec = (PendingIntentRecord)sender;
3991 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003992 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 .getPackageUid(rec.key.packageName);
3994 if (uid != Binder.getCallingUid()) {
3995 String msg = "Permission Denial: cancelIntentSender() from pid="
3996 + Binder.getCallingPid()
3997 + ", uid=" + Binder.getCallingUid()
3998 + " is not allowed to cancel packges "
3999 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004000 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004001 throw new SecurityException(msg);
4002 }
4003 } catch (RemoteException e) {
4004 throw new SecurityException(e);
4005 }
4006 cancelIntentSenderLocked(rec, true);
4007 }
4008 }
4009
4010 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4011 rec.canceled = true;
4012 mIntentSenderRecords.remove(rec.key);
4013 if (cleanActivity && rec.key.activity != null) {
4014 rec.key.activity.pendingResults.remove(rec.ref);
4015 }
4016 }
4017
4018 public String getPackageForIntentSender(IIntentSender pendingResult) {
4019 if (!(pendingResult instanceof PendingIntentRecord)) {
4020 return null;
4021 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004022 try {
4023 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4024 return res.key.packageName;
4025 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004026 }
4027 return null;
4028 }
4029
4030 public void setProcessLimit(int max) {
4031 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4032 "setProcessLimit()");
4033 mProcessLimit = max;
4034 }
4035
4036 public int getProcessLimit() {
4037 return mProcessLimit;
4038 }
4039
4040 void foregroundTokenDied(ForegroundToken token) {
4041 synchronized (ActivityManagerService.this) {
4042 synchronized (mPidsSelfLocked) {
4043 ForegroundToken cur
4044 = mForegroundProcesses.get(token.pid);
4045 if (cur != token) {
4046 return;
4047 }
4048 mForegroundProcesses.remove(token.pid);
4049 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4050 if (pr == null) {
4051 return;
4052 }
4053 pr.forcingToForeground = null;
4054 pr.foregroundServices = false;
4055 }
4056 updateOomAdjLocked();
4057 }
4058 }
4059
4060 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4061 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4062 "setProcessForeground()");
4063 synchronized(this) {
4064 boolean changed = false;
4065
4066 synchronized (mPidsSelfLocked) {
4067 ProcessRecord pr = mPidsSelfLocked.get(pid);
4068 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004069 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004070 return;
4071 }
4072 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4073 if (oldToken != null) {
4074 oldToken.token.unlinkToDeath(oldToken, 0);
4075 mForegroundProcesses.remove(pid);
4076 pr.forcingToForeground = null;
4077 changed = true;
4078 }
4079 if (isForeground && token != null) {
4080 ForegroundToken newToken = new ForegroundToken() {
4081 public void binderDied() {
4082 foregroundTokenDied(this);
4083 }
4084 };
4085 newToken.pid = pid;
4086 newToken.token = token;
4087 try {
4088 token.linkToDeath(newToken, 0);
4089 mForegroundProcesses.put(pid, newToken);
4090 pr.forcingToForeground = token;
4091 changed = true;
4092 } catch (RemoteException e) {
4093 // If the process died while doing this, we will later
4094 // do the cleanup with the process death link.
4095 }
4096 }
4097 }
4098
4099 if (changed) {
4100 updateOomAdjLocked();
4101 }
4102 }
4103 }
4104
4105 // =========================================================
4106 // PERMISSIONS
4107 // =========================================================
4108
4109 static class PermissionController extends IPermissionController.Stub {
4110 ActivityManagerService mActivityManagerService;
4111 PermissionController(ActivityManagerService activityManagerService) {
4112 mActivityManagerService = activityManagerService;
4113 }
4114
4115 public boolean checkPermission(String permission, int pid, int uid) {
4116 return mActivityManagerService.checkPermission(permission, pid,
4117 uid) == PackageManager.PERMISSION_GRANTED;
4118 }
4119 }
4120
4121 /**
4122 * This can be called with or without the global lock held.
4123 */
4124 int checkComponentPermission(String permission, int pid, int uid,
4125 int reqUid) {
4126 // We might be performing an operation on behalf of an indirect binder
4127 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4128 // client identity accordingly before proceeding.
4129 Identity tlsIdentity = sCallerIdentity.get();
4130 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004131 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4133 uid = tlsIdentity.uid;
4134 pid = tlsIdentity.pid;
4135 }
4136
4137 // Root, system server and our own process get to do everything.
4138 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4139 !Process.supportsProcesses()) {
4140 return PackageManager.PERMISSION_GRANTED;
4141 }
4142 // If the target requires a specific UID, always fail for others.
4143 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004144 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004145 return PackageManager.PERMISSION_DENIED;
4146 }
4147 if (permission == null) {
4148 return PackageManager.PERMISSION_GRANTED;
4149 }
4150 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004151 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004152 .checkUidPermission(permission, uid);
4153 } catch (RemoteException e) {
4154 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004155 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004156 }
4157 return PackageManager.PERMISSION_DENIED;
4158 }
4159
4160 /**
4161 * As the only public entry point for permissions checking, this method
4162 * can enforce the semantic that requesting a check on a null global
4163 * permission is automatically denied. (Internally a null permission
4164 * string is used when calling {@link #checkComponentPermission} in cases
4165 * when only uid-based security is needed.)
4166 *
4167 * This can be called with or without the global lock held.
4168 */
4169 public int checkPermission(String permission, int pid, int uid) {
4170 if (permission == null) {
4171 return PackageManager.PERMISSION_DENIED;
4172 }
4173 return checkComponentPermission(permission, pid, uid, -1);
4174 }
4175
4176 /**
4177 * Binder IPC calls go through the public entry point.
4178 * This can be called with or without the global lock held.
4179 */
4180 int checkCallingPermission(String permission) {
4181 return checkPermission(permission,
4182 Binder.getCallingPid(),
4183 Binder.getCallingUid());
4184 }
4185
4186 /**
4187 * This can be called with or without the global lock held.
4188 */
4189 void enforceCallingPermission(String permission, String func) {
4190 if (checkCallingPermission(permission)
4191 == PackageManager.PERMISSION_GRANTED) {
4192 return;
4193 }
4194
4195 String msg = "Permission Denial: " + func + " from pid="
4196 + Binder.getCallingPid()
4197 + ", uid=" + Binder.getCallingUid()
4198 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004199 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200 throw new SecurityException(msg);
4201 }
4202
4203 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004204 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4205 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4206 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4207 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4208 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004209 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004210 // Is the component private from the target uid?
4211 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4212
4213 // Acceptable if the there is no read permission needed from the
4214 // target or the target is holding the read permission.
4215 if (!readPerm) {
4216 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004217 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004218 == PackageManager.PERMISSION_GRANTED)) {
4219 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004220 }
4221 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004222
4223 // Acceptable if the there is no write permission needed from the
4224 // target or the target is holding the read permission.
4225 if (!writePerm) {
4226 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004227 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004228 == PackageManager.PERMISSION_GRANTED)) {
4229 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 }
4231 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004232
4233 // Acceptable if there is a path permission matching the URI that
4234 // the target holds the permission on.
4235 PathPermission[] pps = pi.pathPermissions;
4236 if (pps != null && (!readPerm || !writePerm)) {
4237 final String path = uri.getPath();
4238 int i = pps.length;
4239 while (i > 0 && (!readPerm || !writePerm)) {
4240 i--;
4241 PathPermission pp = pps[i];
4242 if (!readPerm) {
4243 final String pprperm = pp.getReadPermission();
4244 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4245 + pprperm + " for " + pp.getPath()
4246 + ": match=" + pp.match(path)
4247 + " check=" + pm.checkUidPermission(pprperm, uid));
4248 if (pprperm != null && pp.match(path) &&
4249 (pm.checkUidPermission(pprperm, uid)
4250 == PackageManager.PERMISSION_GRANTED)) {
4251 readPerm = true;
4252 }
4253 }
4254 if (!writePerm) {
4255 final String ppwperm = pp.getWritePermission();
4256 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4257 + ppwperm + " for " + pp.getPath()
4258 + ": match=" + pp.match(path)
4259 + " check=" + pm.checkUidPermission(ppwperm, uid));
4260 if (ppwperm != null && pp.match(path) &&
4261 (pm.checkUidPermission(ppwperm, uid)
4262 == PackageManager.PERMISSION_GRANTED)) {
4263 writePerm = true;
4264 }
4265 }
4266 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004268 } catch (RemoteException e) {
4269 return false;
4270 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004271
4272 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004273 }
4274
4275 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4276 int modeFlags) {
4277 // Root gets to do everything.
4278 if (uid == 0 || !Process.supportsProcesses()) {
4279 return true;
4280 }
4281 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4282 if (perms == null) return false;
4283 UriPermission perm = perms.get(uri);
4284 if (perm == null) return false;
4285 return (modeFlags&perm.modeFlags) == modeFlags;
4286 }
4287
4288 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4289 // Another redirected-binder-call permissions check as in
4290 // {@link checkComponentPermission}.
4291 Identity tlsIdentity = sCallerIdentity.get();
4292 if (tlsIdentity != null) {
4293 uid = tlsIdentity.uid;
4294 pid = tlsIdentity.pid;
4295 }
4296
4297 // Our own process gets to do everything.
4298 if (pid == MY_PID) {
4299 return PackageManager.PERMISSION_GRANTED;
4300 }
4301 synchronized(this) {
4302 return checkUriPermissionLocked(uri, uid, modeFlags)
4303 ? PackageManager.PERMISSION_GRANTED
4304 : PackageManager.PERMISSION_DENIED;
4305 }
4306 }
4307
Dianne Hackborn39792d22010-08-19 18:01:52 -07004308 /**
4309 * Check if the targetPkg can be granted permission to access uri by
4310 * the callingUid using the given modeFlags. Throws a security exception
4311 * if callingUid is not allowed to do this. Returns the uid of the target
4312 * if the URI permission grant should be performed; returns -1 if it is not
4313 * needed (for example targetPkg already has permission to access the URI).
4314 */
4315 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4316 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4318 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4319 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004320 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004321 }
4322
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004323 if (targetPkg != null) {
4324 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4325 "Checking grant " + targetPkg + " permission to " + uri);
4326 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004327
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004328 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004329
4330 // If this is not a content: uri, we can't do anything with it.
4331 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004332 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004333 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004334 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004335 }
4336
4337 String name = uri.getAuthority();
4338 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004339 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 if (cpr != null) {
4341 pi = cpr.info;
4342 } else {
4343 try {
4344 pi = pm.resolveContentProvider(name,
4345 PackageManager.GET_URI_PERMISSION_PATTERNS);
4346 } catch (RemoteException ex) {
4347 }
4348 }
4349 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004350 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004351 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004352 }
4353
4354 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004355 if (targetPkg != null) {
4356 try {
4357 targetUid = pm.getPackageUid(targetPkg);
4358 if (targetUid < 0) {
4359 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4360 "Can't grant URI permission no uid for: " + targetPkg);
4361 return -1;
4362 }
4363 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004364 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004365 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004366 } else {
4367 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368 }
4369
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004370 if (targetUid >= 0) {
4371 // First... does the target actually need this permission?
4372 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4373 // No need to grant the target this permission.
4374 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4375 "Target " + targetPkg + " already has full permission to " + uri);
4376 return -1;
4377 }
4378 } else {
4379 // First... there is no target package, so can anyone access it?
4380 boolean allowed = pi.exported;
4381 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4382 if (pi.readPermission != null) {
4383 allowed = false;
4384 }
4385 }
4386 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4387 if (pi.writePermission != null) {
4388 allowed = false;
4389 }
4390 }
4391 if (allowed) {
4392 return -1;
4393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 }
4395
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004396 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 if (!pi.grantUriPermissions) {
4398 throw new SecurityException("Provider " + pi.packageName
4399 + "/" + pi.name
4400 + " does not allow granting of Uri permissions (uri "
4401 + uri + ")");
4402 }
4403 if (pi.uriPermissionPatterns != null) {
4404 final int N = pi.uriPermissionPatterns.length;
4405 boolean allowed = false;
4406 for (int i=0; i<N; i++) {
4407 if (pi.uriPermissionPatterns[i] != null
4408 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4409 allowed = true;
4410 break;
4411 }
4412 }
4413 if (!allowed) {
4414 throw new SecurityException("Provider " + pi.packageName
4415 + "/" + pi.name
4416 + " does not allow granting of permission to path of Uri "
4417 + uri);
4418 }
4419 }
4420
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004421 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004422 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004423 if (callingUid != Process.myUid()) {
4424 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4425 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4426 throw new SecurityException("Uid " + callingUid
4427 + " does not have permission to uri " + uri);
4428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004429 }
4430 }
4431
Dianne Hackborn39792d22010-08-19 18:01:52 -07004432 return targetUid;
4433 }
4434
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004435 public int checkGrantUriPermission(int callingUid, String targetPkg,
4436 Uri uri, int modeFlags) {
4437 synchronized(this) {
4438 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4439 }
4440 }
4441
Dianne Hackborn39792d22010-08-19 18:01:52 -07004442 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4443 Uri uri, int modeFlags, UriPermissionOwner owner) {
4444 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4445 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4446 if (modeFlags == 0) {
4447 return;
4448 }
4449
4450 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 // to the uri, and the target doesn't. Let's now give this to
4452 // the target.
4453
Joe Onorato8a9b2202010-02-26 18:56:32 -08004454 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004455 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 HashMap<Uri, UriPermission> targetUris
4458 = mGrantedUriPermissions.get(targetUid);
4459 if (targetUris == null) {
4460 targetUris = new HashMap<Uri, UriPermission>();
4461 mGrantedUriPermissions.put(targetUid, targetUris);
4462 }
4463
4464 UriPermission perm = targetUris.get(uri);
4465 if (perm == null) {
4466 perm = new UriPermission(targetUid, uri);
4467 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004468 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004470 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004471 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004472 perm.globalModeFlags |= modeFlags;
4473 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004474 perm.readOwners.add(owner);
4475 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004477 perm.writeOwners.add(owner);
4478 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 }
4480 }
4481
Dianne Hackborn39792d22010-08-19 18:01:52 -07004482 void grantUriPermissionLocked(int callingUid,
4483 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004484 if (targetPkg == null) {
4485 throw new NullPointerException("targetPkg");
4486 }
4487
Dianne Hackborn39792d22010-08-19 18:01:52 -07004488 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4489 if (targetUid < 0) {
4490 return;
4491 }
4492
4493 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4494 }
4495
4496 /**
4497 * Like checkGrantUriPermissionLocked, but takes an Intent.
4498 */
4499 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4500 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004501 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004502 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004503 + " from " + intent + "; flags=0x"
4504 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4505
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004506 if (targetPkg == null) {
4507 throw new NullPointerException("targetPkg");
4508 }
4509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004511 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004512 }
4513 Uri data = intent.getData();
4514 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004515 return -1;
4516 }
4517 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4518 intent.getFlags());
4519 }
4520
4521 /**
4522 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4523 */
4524 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4525 String targetPkg, Intent intent, UriPermissionOwner owner) {
4526 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4527 intent.getFlags(), owner);
4528 }
4529
4530 void grantUriPermissionFromIntentLocked(int callingUid,
4531 String targetPkg, Intent intent, UriPermissionOwner owner) {
4532 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4533 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 return;
4535 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004536
4537 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004538 }
4539
4540 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4541 Uri uri, int modeFlags) {
4542 synchronized(this) {
4543 final ProcessRecord r = getRecordForAppLocked(caller);
4544 if (r == null) {
4545 throw new SecurityException("Unable to find app for caller "
4546 + caller
4547 + " when granting permission to uri " + uri);
4548 }
4549 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004550 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 }
4552 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004553 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 }
4555
4556 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4557 null);
4558 }
4559 }
4560
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004561 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004562 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4563 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4564 HashMap<Uri, UriPermission> perms
4565 = mGrantedUriPermissions.get(perm.uid);
4566 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004567 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004568 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004569 perms.remove(perm.uri);
4570 if (perms.size() == 0) {
4571 mGrantedUriPermissions.remove(perm.uid);
4572 }
4573 }
4574 }
4575 }
4576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004577 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4578 int modeFlags) {
4579 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4580 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4581 if (modeFlags == 0) {
4582 return;
4583 }
4584
Joe Onorato8a9b2202010-02-26 18:56:32 -08004585 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004586 "Revoking all granted permissions to " + uri);
4587
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004588 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004589
4590 final String authority = uri.getAuthority();
4591 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004592 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 if (cpr != null) {
4594 pi = cpr.info;
4595 } else {
4596 try {
4597 pi = pm.resolveContentProvider(authority,
4598 PackageManager.GET_URI_PERMISSION_PATTERNS);
4599 } catch (RemoteException ex) {
4600 }
4601 }
4602 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004603 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004604 return;
4605 }
4606
4607 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004608 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004609 // Right now, if you are not the original owner of the permission,
4610 // you are not allowed to revoke it.
4611 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4612 throw new SecurityException("Uid " + callingUid
4613 + " does not have permission to uri " + uri);
4614 //}
4615 }
4616
4617 // Go through all of the permissions and remove any that match.
4618 final List<String> SEGMENTS = uri.getPathSegments();
4619 if (SEGMENTS != null) {
4620 final int NS = SEGMENTS.size();
4621 int N = mGrantedUriPermissions.size();
4622 for (int i=0; i<N; i++) {
4623 HashMap<Uri, UriPermission> perms
4624 = mGrantedUriPermissions.valueAt(i);
4625 Iterator<UriPermission> it = perms.values().iterator();
4626 toploop:
4627 while (it.hasNext()) {
4628 UriPermission perm = it.next();
4629 Uri targetUri = perm.uri;
4630 if (!authority.equals(targetUri.getAuthority())) {
4631 continue;
4632 }
4633 List<String> targetSegments = targetUri.getPathSegments();
4634 if (targetSegments == null) {
4635 continue;
4636 }
4637 if (targetSegments.size() < NS) {
4638 continue;
4639 }
4640 for (int j=0; j<NS; j++) {
4641 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4642 continue toploop;
4643 }
4644 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004645 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004646 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004647 perm.clearModes(modeFlags);
4648 if (perm.modeFlags == 0) {
4649 it.remove();
4650 }
4651 }
4652 if (perms.size() == 0) {
4653 mGrantedUriPermissions.remove(
4654 mGrantedUriPermissions.keyAt(i));
4655 N--;
4656 i--;
4657 }
4658 }
4659 }
4660 }
4661
4662 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4663 int modeFlags) {
4664 synchronized(this) {
4665 final ProcessRecord r = getRecordForAppLocked(caller);
4666 if (r == null) {
4667 throw new SecurityException("Unable to find app for caller "
4668 + caller
4669 + " when revoking permission to uri " + uri);
4670 }
4671 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004672 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004673 return;
4674 }
4675
4676 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4677 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4678 if (modeFlags == 0) {
4679 return;
4680 }
4681
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004682 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004683
4684 final String authority = uri.getAuthority();
4685 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004686 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004687 if (cpr != null) {
4688 pi = cpr.info;
4689 } else {
4690 try {
4691 pi = pm.resolveContentProvider(authority,
4692 PackageManager.GET_URI_PERMISSION_PATTERNS);
4693 } catch (RemoteException ex) {
4694 }
4695 }
4696 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004697 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004698 return;
4699 }
4700
4701 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4702 }
4703 }
4704
Dianne Hackborn7e269642010-08-25 19:50:20 -07004705 @Override
4706 public IBinder newUriPermissionOwner(String name) {
4707 synchronized(this) {
4708 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4709 return owner.getExternalTokenLocked();
4710 }
4711 }
4712
4713 @Override
4714 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4715 Uri uri, int modeFlags) {
4716 synchronized(this) {
4717 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4718 if (owner == null) {
4719 throw new IllegalArgumentException("Unknown owner: " + token);
4720 }
4721 if (fromUid != Binder.getCallingUid()) {
4722 if (Binder.getCallingUid() != Process.myUid()) {
4723 // Only system code can grant URI permissions on behalf
4724 // of other users.
4725 throw new SecurityException("nice try");
4726 }
4727 }
4728 if (targetPkg == null) {
4729 throw new IllegalArgumentException("null target");
4730 }
4731 if (uri == null) {
4732 throw new IllegalArgumentException("null uri");
4733 }
4734
4735 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4736 }
4737 }
4738
4739 @Override
4740 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4741 synchronized(this) {
4742 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4743 if (owner == null) {
4744 throw new IllegalArgumentException("Unknown owner: " + token);
4745 }
4746
4747 if (uri == null) {
4748 owner.removeUriPermissionsLocked(mode);
4749 } else {
4750 owner.removeUriPermissionLocked(uri, mode);
4751 }
4752 }
4753 }
4754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004755 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4756 synchronized (this) {
4757 ProcessRecord app =
4758 who != null ? getRecordForAppLocked(who) : null;
4759 if (app == null) return;
4760
4761 Message msg = Message.obtain();
4762 msg.what = WAIT_FOR_DEBUGGER_MSG;
4763 msg.obj = app;
4764 msg.arg1 = waiting ? 1 : 0;
4765 mHandler.sendMessage(msg);
4766 }
4767 }
4768
4769 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4770 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004771 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004772 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004773 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004774 }
4775
4776 // =========================================================
4777 // TASK MANAGEMENT
4778 // =========================================================
4779
4780 public List getTasks(int maxNum, int flags,
4781 IThumbnailReceiver receiver) {
4782 ArrayList list = new ArrayList();
4783
4784 PendingThumbnailsRecord pending = null;
4785 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004786 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004787
4788 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004789 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004790 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4791 + ", receiver=" + receiver);
4792
4793 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4794 != PackageManager.PERMISSION_GRANTED) {
4795 if (receiver != null) {
4796 // If the caller wants to wait for pending thumbnails,
4797 // it ain't gonna get them.
4798 try {
4799 receiver.finished();
4800 } catch (RemoteException ex) {
4801 }
4802 }
4803 String msg = "Permission Denial: getTasks() from pid="
4804 + Binder.getCallingPid()
4805 + ", uid=" + Binder.getCallingUid()
4806 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004807 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004808 throw new SecurityException(msg);
4809 }
4810
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004811 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004812 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004813 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004814 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 CharSequence topDescription = null;
4816 TaskRecord curTask = null;
4817 int numActivities = 0;
4818 int numRunning = 0;
4819 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004820 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004821 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004822 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004823
4824 // Initialize state for next task if needed.
4825 if (top == null ||
4826 (top.state == ActivityState.INITIALIZING
4827 && top.task == r.task)) {
4828 top = r;
4829 topDescription = r.description;
4830 curTask = r.task;
4831 numActivities = numRunning = 0;
4832 }
4833
4834 // Add 'r' into the current task.
4835 numActivities++;
4836 if (r.app != null && r.app.thread != null) {
4837 numRunning++;
4838 }
4839 if (topDescription == null) {
4840 topDescription = r.description;
4841 }
4842
Joe Onorato8a9b2202010-02-26 18:56:32 -08004843 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004844 TAG, r.intent.getComponent().flattenToShortString()
4845 + ": task=" + r.task);
4846
4847 // If the next one is a different task, generate a new
4848 // TaskInfo entry for what we have.
4849 if (next == null || next.task != curTask) {
4850 ActivityManager.RunningTaskInfo ci
4851 = new ActivityManager.RunningTaskInfo();
4852 ci.id = curTask.taskId;
4853 ci.baseActivity = r.intent.getComponent();
4854 ci.topActivity = top.intent.getComponent();
4855 ci.thumbnail = top.thumbnail;
4856 ci.description = topDescription;
4857 ci.numActivities = numActivities;
4858 ci.numRunning = numRunning;
4859 //System.out.println(
4860 // "#" + maxNum + ": " + " descr=" + ci.description);
4861 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004862 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 TAG, "State=" + top.state + "Idle=" + top.idle
4864 + " app=" + top.app
4865 + " thr=" + (top.app != null ? top.app.thread : null));
4866 if (top.state == ActivityState.RESUMED
4867 || top.state == ActivityState.PAUSING) {
4868 if (top.idle && top.app != null
4869 && top.app.thread != null) {
4870 topRecord = top;
4871 topThumbnail = top.app.thread;
4872 } else {
4873 top.thumbnailNeeded = true;
4874 }
4875 }
4876 if (pending == null) {
4877 pending = new PendingThumbnailsRecord(receiver);
4878 }
4879 pending.pendingRecords.add(top);
4880 }
4881 list.add(ci);
4882 maxNum--;
4883 top = null;
4884 }
4885 }
4886
4887 if (pending != null) {
4888 mPendingThumbnails.add(pending);
4889 }
4890 }
4891
Joe Onorato8a9b2202010-02-26 18:56:32 -08004892 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004893
4894 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004895 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 try {
4897 topThumbnail.requestThumbnail(topRecord);
4898 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004899 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004900 sendPendingThumbnail(null, topRecord, null, null, true);
4901 }
4902 }
4903
4904 if (pending == null && receiver != null) {
4905 // In this case all thumbnails were available and the client
4906 // is being asked to be told when the remaining ones come in...
4907 // which is unusually, since the top-most currently running
4908 // activity should never have a canned thumbnail! Oh well.
4909 try {
4910 receiver.finished();
4911 } catch (RemoteException ex) {
4912 }
4913 }
4914
4915 return list;
4916 }
4917
4918 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4919 int flags) {
4920 synchronized (this) {
4921 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4922 "getRecentTasks()");
4923
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004924 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004926 final int N = mRecentTasks.size();
4927 ArrayList<ActivityManager.RecentTaskInfo> res
4928 = new ArrayList<ActivityManager.RecentTaskInfo>(
4929 maxNum < N ? maxNum : N);
4930 for (int i=0; i<N && maxNum > 0; i++) {
4931 TaskRecord tr = mRecentTasks.get(i);
4932 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4933 || (tr.intent == null)
4934 || ((tr.intent.getFlags()
4935 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4936 ActivityManager.RecentTaskInfo rti
4937 = new ActivityManager.RecentTaskInfo();
4938 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4939 rti.baseIntent = new Intent(
4940 tr.intent != null ? tr.intent : tr.affinityIntent);
4941 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004942
4943 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4944 // Check whether this activity is currently available.
4945 try {
4946 if (rti.origActivity != null) {
4947 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4948 continue;
4949 }
4950 } else if (rti.baseIntent != null) {
4951 if (pm.queryIntentActivities(rti.baseIntent,
4952 null, 0) == null) {
4953 continue;
4954 }
4955 }
4956 } catch (RemoteException e) {
4957 // Will never happen.
4958 }
4959 }
4960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 res.add(rti);
4962 maxNum--;
4963 }
4964 }
4965 return res;
4966 }
4967 }
4968
4969 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4970 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004971 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004972 TaskRecord jt = startTask;
4973
4974 // First look backwards
4975 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004976 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 if (r.task != jt) {
4978 jt = r.task;
4979 if (affinity.equals(jt.affinity)) {
4980 return j;
4981 }
4982 }
4983 }
4984
4985 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004986 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004987 jt = startTask;
4988 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004989 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 if (r.task != jt) {
4991 if (affinity.equals(jt.affinity)) {
4992 return j;
4993 }
4994 jt = r.task;
4995 }
4996 }
4997
4998 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004999 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 return N-1;
5001 }
5002
5003 return -1;
5004 }
5005
5006 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005007 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008 */
5009 public void moveTaskToFront(int task) {
5010 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5011 "moveTaskToFront()");
5012
5013 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005014 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5015 Binder.getCallingUid(), "Task to front")) {
5016 return;
5017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 final long origId = Binder.clearCallingIdentity();
5019 try {
5020 int N = mRecentTasks.size();
5021 for (int i=0; i<N; i++) {
5022 TaskRecord tr = mRecentTasks.get(i);
5023 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005024 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 return;
5026 }
5027 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005028 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5029 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005031 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 return;
5033 }
5034 }
5035 } finally {
5036 Binder.restoreCallingIdentity(origId);
5037 }
5038 }
5039 }
5040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005041 public void moveTaskToBack(int task) {
5042 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5043 "moveTaskToBack()");
5044
5045 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005046 if (mMainStack.mResumedActivity != null
5047 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005048 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5049 Binder.getCallingUid(), "Task to back")) {
5050 return;
5051 }
5052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005054 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005055 Binder.restoreCallingIdentity(origId);
5056 }
5057 }
5058
5059 /**
5060 * Moves an activity, and all of the other activities within the same task, to the bottom
5061 * of the history stack. The activity's order within the task is unchanged.
5062 *
5063 * @param token A reference to the activity we wish to move
5064 * @param nonRoot If false then this only works if the activity is the root
5065 * of a task; if true it will work for any activity in a task.
5066 * @return Returns true if the move completed, false if not.
5067 */
5068 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5069 synchronized(this) {
5070 final long origId = Binder.clearCallingIdentity();
5071 int taskId = getTaskForActivityLocked(token, !nonRoot);
5072 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005073 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 }
5075 Binder.restoreCallingIdentity(origId);
5076 }
5077 return false;
5078 }
5079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005080 public void moveTaskBackwards(int task) {
5081 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5082 "moveTaskBackwards()");
5083
5084 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005085 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5086 Binder.getCallingUid(), "Task backwards")) {
5087 return;
5088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005089 final long origId = Binder.clearCallingIdentity();
5090 moveTaskBackwardsLocked(task);
5091 Binder.restoreCallingIdentity(origId);
5092 }
5093 }
5094
5095 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005096 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 }
5098
5099 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5100 synchronized(this) {
5101 return getTaskForActivityLocked(token, onlyRoot);
5102 }
5103 }
5104
5105 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005106 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005107 TaskRecord lastTask = null;
5108 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005109 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 if (r == token) {
5111 if (!onlyRoot || lastTask != r.task) {
5112 return r.task.taskId;
5113 }
5114 return -1;
5115 }
5116 lastTask = r.task;
5117 }
5118
5119 return -1;
5120 }
5121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005122 public void finishOtherInstances(IBinder token, ComponentName className) {
5123 synchronized(this) {
5124 final long origId = Binder.clearCallingIdentity();
5125
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005126 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005127 TaskRecord lastTask = null;
5128 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005129 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 if (r.realActivity.equals(className)
5131 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005132 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005133 null, "others")) {
5134 i--;
5135 N--;
5136 }
5137 }
5138 lastTask = r.task;
5139 }
5140
5141 Binder.restoreCallingIdentity(origId);
5142 }
5143 }
5144
5145 // =========================================================
5146 // THUMBNAILS
5147 // =========================================================
5148
5149 public void reportThumbnail(IBinder token,
5150 Bitmap thumbnail, CharSequence description) {
5151 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5152 final long origId = Binder.clearCallingIdentity();
5153 sendPendingThumbnail(null, token, thumbnail, description, true);
5154 Binder.restoreCallingIdentity(origId);
5155 }
5156
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005157 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005158 Bitmap thumbnail, CharSequence description, boolean always) {
5159 TaskRecord task = null;
5160 ArrayList receivers = null;
5161
5162 //System.out.println("Send pending thumbnail: " + r);
5163
5164 synchronized(this) {
5165 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005166 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005167 if (index < 0) {
5168 return;
5169 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005170 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005171 }
5172 if (thumbnail == null) {
5173 thumbnail = r.thumbnail;
5174 description = r.description;
5175 }
5176 if (thumbnail == null && !always) {
5177 // If there is no thumbnail, and this entry is not actually
5178 // going away, then abort for now and pick up the next
5179 // thumbnail we get.
5180 return;
5181 }
5182 task = r.task;
5183
5184 int N = mPendingThumbnails.size();
5185 int i=0;
5186 while (i<N) {
5187 PendingThumbnailsRecord pr =
5188 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5189 //System.out.println("Looking in " + pr.pendingRecords);
5190 if (pr.pendingRecords.remove(r)) {
5191 if (receivers == null) {
5192 receivers = new ArrayList();
5193 }
5194 receivers.add(pr);
5195 if (pr.pendingRecords.size() == 0) {
5196 pr.finished = true;
5197 mPendingThumbnails.remove(i);
5198 N--;
5199 continue;
5200 }
5201 }
5202 i++;
5203 }
5204 }
5205
5206 if (receivers != null) {
5207 final int N = receivers.size();
5208 for (int i=0; i<N; i++) {
5209 try {
5210 PendingThumbnailsRecord pr =
5211 (PendingThumbnailsRecord)receivers.get(i);
5212 pr.receiver.newThumbnail(
5213 task != null ? task.taskId : -1, thumbnail, description);
5214 if (pr.finished) {
5215 pr.receiver.finished();
5216 }
5217 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005218 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005219 }
5220 }
5221 }
5222 }
5223
5224 // =========================================================
5225 // CONTENT PROVIDERS
5226 // =========================================================
5227
5228 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5229 List providers = null;
5230 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005231 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005233 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005234 } catch (RemoteException ex) {
5235 }
5236 if (providers != null) {
5237 final int N = providers.size();
5238 for (int i=0; i<N; i++) {
5239 ProviderInfo cpi =
5240 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005241 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005242 if (cpr == null) {
5243 cpr = new ContentProviderRecord(cpi, app.info);
5244 mProvidersByClass.put(cpi.name, cpr);
5245 }
5246 app.pubProviders.put(cpi.name, cpr);
5247 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005248 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 }
5250 }
5251 return providers;
5252 }
5253
5254 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005255 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5257 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5258 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5259 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005260 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005261 return null;
5262 }
5263 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5264 cpi.exported ? -1 : cpi.applicationInfo.uid)
5265 == PackageManager.PERMISSION_GRANTED) {
5266 return null;
5267 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005268
5269 PathPermission[] pps = cpi.pathPermissions;
5270 if (pps != null) {
5271 int i = pps.length;
5272 while (i > 0) {
5273 i--;
5274 PathPermission pp = pps[i];
5275 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5276 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005277 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005278 return null;
5279 }
5280 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5281 cpi.exported ? -1 : cpi.applicationInfo.uid)
5282 == PackageManager.PERMISSION_GRANTED) {
5283 return null;
5284 }
5285 }
5286 }
5287
Dianne Hackbornb424b632010-08-18 15:59:05 -07005288 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5289 if (perms != null) {
5290 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5291 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5292 return null;
5293 }
5294 }
5295 }
5296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005297 String msg = "Permission Denial: opening provider " + cpi.name
5298 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5299 + ", uid=" + callingUid + ") requires "
5300 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005301 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 return msg;
5303 }
5304
5305 private final ContentProviderHolder getContentProviderImpl(
5306 IApplicationThread caller, String name) {
5307 ContentProviderRecord cpr;
5308 ProviderInfo cpi = null;
5309
5310 synchronized(this) {
5311 ProcessRecord r = null;
5312 if (caller != null) {
5313 r = getRecordForAppLocked(caller);
5314 if (r == null) {
5315 throw new SecurityException(
5316 "Unable to find app for caller " + caller
5317 + " (pid=" + Binder.getCallingPid()
5318 + ") when getting content provider " + name);
5319 }
5320 }
5321
5322 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005323 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 if (cpr != null) {
5325 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005326 String msg;
5327 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5328 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 }
5330
5331 if (r != null && cpr.canRunHere(r)) {
5332 // This provider has been published or is in the process
5333 // of being published... but it is also allowed to run
5334 // in the caller's process, so don't make a connection
5335 // and just let the caller instantiate its own instance.
5336 if (cpr.provider != null) {
5337 // don't give caller the provider object, it needs
5338 // to make its own.
5339 cpr = new ContentProviderRecord(cpr);
5340 }
5341 return cpr;
5342 }
5343
5344 final long origId = Binder.clearCallingIdentity();
5345
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005346 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005347 // return it right away.
5348 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005349 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005350 "Adding provider requested by "
5351 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005352 + cpr.info.processName);
5353 Integer cnt = r.conProviders.get(cpr);
5354 if (cnt == null) {
5355 r.conProviders.put(cpr, new Integer(1));
5356 } else {
5357 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005359 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005360 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5361 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005362 // make sure to count it as being accessed and thus
5363 // back up on the LRU list. This is good because
5364 // content providers are often expensive to start.
5365 updateLruProcessLocked(cpr.app, false, true);
5366 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005367 } else {
5368 cpr.externals++;
5369 }
5370
5371 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005372 updateOomAdjLocked(cpr.app);
5373 }
5374
5375 Binder.restoreCallingIdentity(origId);
5376
5377 } else {
5378 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005379 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005380 resolveContentProvider(name,
5381 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005382 } catch (RemoteException ex) {
5383 }
5384 if (cpi == null) {
5385 return null;
5386 }
5387
Dianne Hackbornb424b632010-08-18 15:59:05 -07005388 String msg;
5389 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5390 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005391 }
5392
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005393 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005394 && !cpi.processName.equals("system")) {
5395 // If this content provider does not run in the system
5396 // process, and the system is not yet ready to run other
5397 // processes, then fail fast instead of hanging.
5398 throw new IllegalArgumentException(
5399 "Attempt to launch content provider before system ready");
5400 }
5401
Dianne Hackborn860755f2010-06-03 18:47:52 -07005402 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005403 final boolean firstClass = cpr == null;
5404 if (firstClass) {
5405 try {
5406 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005407 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408 getApplicationInfo(
5409 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005410 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005411 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005412 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005413 + cpi.name);
5414 return null;
5415 }
5416 cpr = new ContentProviderRecord(cpi, ai);
5417 } catch (RemoteException ex) {
5418 // pm is in same process, this will never happen.
5419 }
5420 }
5421
5422 if (r != null && cpr.canRunHere(r)) {
5423 // If this is a multiprocess provider, then just return its
5424 // info and allow the caller to instantiate it. Only do
5425 // this if the provider is the same user as the caller's
5426 // process, or can run as root (so can be in any process).
5427 return cpr;
5428 }
5429
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005430 if (DEBUG_PROVIDER) {
5431 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005432 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005433 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005434 }
5435
5436 // This is single process, and our app is now connecting to it.
5437 // See if we are already in the process of launching this
5438 // provider.
5439 final int N = mLaunchingProviders.size();
5440 int i;
5441 for (i=0; i<N; i++) {
5442 if (mLaunchingProviders.get(i) == cpr) {
5443 break;
5444 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005445 }
5446
5447 // If the provider is not already being launched, then get it
5448 // started.
5449 if (i >= N) {
5450 final long origId = Binder.clearCallingIdentity();
5451 ProcessRecord proc = startProcessLocked(cpi.processName,
5452 cpr.appInfo, false, 0, "content provider",
5453 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005454 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005455 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005456 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005457 + cpi.applicationInfo.packageName + "/"
5458 + cpi.applicationInfo.uid + " for provider "
5459 + name + ": process is bad");
5460 return null;
5461 }
5462 cpr.launchingApp = proc;
5463 mLaunchingProviders.add(cpr);
5464 Binder.restoreCallingIdentity(origId);
5465 }
5466
5467 // Make sure the provider is published (the same provider class
5468 // may be published under multiple names).
5469 if (firstClass) {
5470 mProvidersByClass.put(cpi.name, cpr);
5471 }
5472 mProvidersByName.put(name, cpr);
5473
5474 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005475 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005476 "Adding provider requested by "
5477 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005478 + cpr.info.processName);
5479 Integer cnt = r.conProviders.get(cpr);
5480 if (cnt == null) {
5481 r.conProviders.put(cpr, new Integer(1));
5482 } else {
5483 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005485 cpr.clients.add(r);
5486 } else {
5487 cpr.externals++;
5488 }
5489 }
5490 }
5491
5492 // Wait for the provider to be published...
5493 synchronized (cpr) {
5494 while (cpr.provider == null) {
5495 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005496 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005497 + cpi.applicationInfo.packageName + "/"
5498 + cpi.applicationInfo.uid + " for provider "
5499 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005500 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501 cpi.applicationInfo.packageName,
5502 cpi.applicationInfo.uid, name);
5503 return null;
5504 }
5505 try {
5506 cpr.wait();
5507 } catch (InterruptedException ex) {
5508 }
5509 }
5510 }
5511 return cpr;
5512 }
5513
5514 public final ContentProviderHolder getContentProvider(
5515 IApplicationThread caller, String name) {
5516 if (caller == null) {
5517 String msg = "null IApplicationThread when getting content provider "
5518 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005519 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005520 throw new SecurityException(msg);
5521 }
5522
5523 return getContentProviderImpl(caller, name);
5524 }
5525
5526 private ContentProviderHolder getContentProviderExternal(String name) {
5527 return getContentProviderImpl(null, name);
5528 }
5529
5530 /**
5531 * Drop a content provider from a ProcessRecord's bookkeeping
5532 * @param cpr
5533 */
5534 public void removeContentProvider(IApplicationThread caller, String name) {
5535 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005536 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005537 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005538 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005539 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005540 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005541 return;
5542 }
5543 final ProcessRecord r = getRecordForAppLocked(caller);
5544 if (r == null) {
5545 throw new SecurityException(
5546 "Unable to find app for caller " + caller +
5547 " when removing content provider " + name);
5548 }
5549 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005550 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005551 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005552 + r.info.processName + " from process "
5553 + localCpr.appInfo.processName);
5554 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005555 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005556 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005557 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 return;
5559 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005560 Integer cnt = r.conProviders.get(localCpr);
5561 if (cnt == null || cnt.intValue() <= 1) {
5562 localCpr.clients.remove(r);
5563 r.conProviders.remove(localCpr);
5564 } else {
5565 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5566 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 }
5568 updateOomAdjLocked();
5569 }
5570 }
5571
5572 private void removeContentProviderExternal(String name) {
5573 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005574 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005575 if(cpr == null) {
5576 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005577 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 return;
5579 }
5580
5581 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005582 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005583 localCpr.externals--;
5584 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005585 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 }
5587 updateOomAdjLocked();
5588 }
5589 }
5590
5591 public final void publishContentProviders(IApplicationThread caller,
5592 List<ContentProviderHolder> providers) {
5593 if (providers == null) {
5594 return;
5595 }
5596
5597 synchronized(this) {
5598 final ProcessRecord r = getRecordForAppLocked(caller);
5599 if (r == null) {
5600 throw new SecurityException(
5601 "Unable to find app for caller " + caller
5602 + " (pid=" + Binder.getCallingPid()
5603 + ") when publishing content providers");
5604 }
5605
5606 final long origId = Binder.clearCallingIdentity();
5607
5608 final int N = providers.size();
5609 for (int i=0; i<N; i++) {
5610 ContentProviderHolder src = providers.get(i);
5611 if (src == null || src.info == null || src.provider == null) {
5612 continue;
5613 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005614 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615 if (dst != null) {
5616 mProvidersByClass.put(dst.info.name, dst);
5617 String names[] = dst.info.authority.split(";");
5618 for (int j = 0; j < names.length; j++) {
5619 mProvidersByName.put(names[j], dst);
5620 }
5621
5622 int NL = mLaunchingProviders.size();
5623 int j;
5624 for (j=0; j<NL; j++) {
5625 if (mLaunchingProviders.get(j) == dst) {
5626 mLaunchingProviders.remove(j);
5627 j--;
5628 NL--;
5629 }
5630 }
5631 synchronized (dst) {
5632 dst.provider = src.provider;
5633 dst.app = r;
5634 dst.notifyAll();
5635 }
5636 updateOomAdjLocked(r);
5637 }
5638 }
5639
5640 Binder.restoreCallingIdentity(origId);
5641 }
5642 }
5643
5644 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005645 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005646 synchronized (mSelf) {
5647 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5648 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005649 if (providers != null) {
5650 for (int i=providers.size()-1; i>=0; i--) {
5651 ProviderInfo pi = (ProviderInfo)providers.get(i);
5652 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5653 Slog.w(TAG, "Not installing system proc provider " + pi.name
5654 + ": not system .apk");
5655 providers.remove(i);
5656 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005657 }
5658 }
5659 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005660 if (providers != null) {
5661 mSystemThread.installSystemProviders(providers);
5662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005663 }
5664
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005665 /**
5666 * Allows app to retrieve the MIME type of a URI without having permission
5667 * to access its content provider.
5668 *
5669 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5670 *
5671 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5672 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5673 */
5674 public String getProviderMimeType(Uri uri) {
5675 final String name = uri.getAuthority();
5676 final long ident = Binder.clearCallingIdentity();
5677 ContentProviderHolder holder = null;
5678
5679 try {
5680 holder = getContentProviderExternal(name);
5681 if (holder != null) {
5682 return holder.provider.getType(uri);
5683 }
5684 } catch (RemoteException e) {
5685 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5686 return null;
5687 } finally {
5688 if (holder != null) {
5689 removeContentProviderExternal(name);
5690 }
5691 Binder.restoreCallingIdentity(ident);
5692 }
5693
5694 return null;
5695 }
5696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005697 // =========================================================
5698 // GLOBAL MANAGEMENT
5699 // =========================================================
5700
5701 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5702 ApplicationInfo info, String customProcess) {
5703 String proc = customProcess != null ? customProcess : info.processName;
5704 BatteryStatsImpl.Uid.Proc ps = null;
5705 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5706 synchronized (stats) {
5707 ps = stats.getProcessStatsLocked(info.uid, proc);
5708 }
5709 return new ProcessRecord(ps, thread, info, proc);
5710 }
5711
5712 final ProcessRecord addAppLocked(ApplicationInfo info) {
5713 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5714
5715 if (app == null) {
5716 app = newProcessRecordLocked(null, info, null);
5717 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005718 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005719 }
5720
5721 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5722 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5723 app.persistent = true;
5724 app.maxAdj = CORE_SERVER_ADJ;
5725 }
5726 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5727 mPersistentStartingProcesses.add(app);
5728 startProcessLocked(app, "added application", app.processName);
5729 }
5730
5731 return app;
5732 }
5733
5734 public void unhandledBack() {
5735 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5736 "unhandledBack()");
5737
5738 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005739 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005740 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005741 TAG, "Performing unhandledBack(): stack size = " + count);
5742 if (count > 1) {
5743 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005744 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005745 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5746 Binder.restoreCallingIdentity(origId);
5747 }
5748 }
5749 }
5750
5751 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5752 String name = uri.getAuthority();
5753 ContentProviderHolder cph = getContentProviderExternal(name);
5754 ParcelFileDescriptor pfd = null;
5755 if (cph != null) {
5756 // We record the binder invoker's uid in thread-local storage before
5757 // going to the content provider to open the file. Later, in the code
5758 // that handles all permissions checks, we look for this uid and use
5759 // that rather than the Activity Manager's own uid. The effect is that
5760 // we do the check against the caller's permissions even though it looks
5761 // to the content provider like the Activity Manager itself is making
5762 // the request.
5763 sCallerIdentity.set(new Identity(
5764 Binder.getCallingPid(), Binder.getCallingUid()));
5765 try {
5766 pfd = cph.provider.openFile(uri, "r");
5767 } catch (FileNotFoundException e) {
5768 // do nothing; pfd will be returned null
5769 } finally {
5770 // Ensure that whatever happens, we clean up the identity state
5771 sCallerIdentity.remove();
5772 }
5773
5774 // We've got the fd now, so we're done with the provider.
5775 removeContentProviderExternal(name);
5776 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005777 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005778 }
5779 return pfd;
5780 }
5781
5782 public void goingToSleep() {
5783 synchronized(this) {
5784 mSleeping = true;
5785 mWindowManager.setEventDispatching(false);
5786
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005787 if (mMainStack.mResumedActivity != null) {
5788 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005789 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005790 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005792
5793 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005794 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005795 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5796 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005797 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005798 }
5799 }
5800
Dianne Hackborn55280a92009-05-07 15:53:46 -07005801 public boolean shutdown(int timeout) {
5802 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5803 != PackageManager.PERMISSION_GRANTED) {
5804 throw new SecurityException("Requires permission "
5805 + android.Manifest.permission.SHUTDOWN);
5806 }
5807
5808 boolean timedout = false;
5809
5810 synchronized(this) {
5811 mShuttingDown = true;
5812 mWindowManager.setEventDispatching(false);
5813
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005814 if (mMainStack.mResumedActivity != null) {
5815 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005816 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005817 while (mMainStack.mResumedActivity != null
5818 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005819 long delay = endTime - System.currentTimeMillis();
5820 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005821 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005822 timedout = true;
5823 break;
5824 }
5825 try {
5826 this.wait();
5827 } catch (InterruptedException e) {
5828 }
5829 }
5830 }
5831 }
5832
5833 mUsageStatsService.shutdown();
5834 mBatteryStatsService.shutdown();
5835
5836 return timedout;
5837 }
5838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005839 public void wakingUp() {
5840 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005841 if (mMainStack.mGoingToSleep.isHeld()) {
5842 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005843 }
5844 mWindowManager.setEventDispatching(true);
5845 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005846 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005847 }
5848 }
5849
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005850 public void stopAppSwitches() {
5851 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5852 != PackageManager.PERMISSION_GRANTED) {
5853 throw new SecurityException("Requires permission "
5854 + android.Manifest.permission.STOP_APP_SWITCHES);
5855 }
5856
5857 synchronized(this) {
5858 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5859 + APP_SWITCH_DELAY_TIME;
5860 mDidAppSwitch = false;
5861 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5862 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5863 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5864 }
5865 }
5866
5867 public void resumeAppSwitches() {
5868 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5869 != PackageManager.PERMISSION_GRANTED) {
5870 throw new SecurityException("Requires permission "
5871 + android.Manifest.permission.STOP_APP_SWITCHES);
5872 }
5873
5874 synchronized(this) {
5875 // Note that we don't execute any pending app switches... we will
5876 // let those wait until either the timeout, or the next start
5877 // activity request.
5878 mAppSwitchesAllowedTime = 0;
5879 }
5880 }
5881
5882 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5883 String name) {
5884 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5885 return true;
5886 }
5887
5888 final int perm = checkComponentPermission(
5889 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5890 callingUid, -1);
5891 if (perm == PackageManager.PERMISSION_GRANTED) {
5892 return true;
5893 }
5894
Joe Onorato8a9b2202010-02-26 18:56:32 -08005895 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005896 return false;
5897 }
5898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005899 public void setDebugApp(String packageName, boolean waitForDebugger,
5900 boolean persistent) {
5901 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5902 "setDebugApp()");
5903
5904 // Note that this is not really thread safe if there are multiple
5905 // callers into it at the same time, but that's not a situation we
5906 // care about.
5907 if (persistent) {
5908 final ContentResolver resolver = mContext.getContentResolver();
5909 Settings.System.putString(
5910 resolver, Settings.System.DEBUG_APP,
5911 packageName);
5912 Settings.System.putInt(
5913 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5914 waitForDebugger ? 1 : 0);
5915 }
5916
5917 synchronized (this) {
5918 if (!persistent) {
5919 mOrigDebugApp = mDebugApp;
5920 mOrigWaitForDebugger = mWaitForDebugger;
5921 }
5922 mDebugApp = packageName;
5923 mWaitForDebugger = waitForDebugger;
5924 mDebugTransient = !persistent;
5925 if (packageName != null) {
5926 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005927 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005928 Binder.restoreCallingIdentity(origId);
5929 }
5930 }
5931 }
5932
5933 public void setAlwaysFinish(boolean enabled) {
5934 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5935 "setAlwaysFinish()");
5936
5937 Settings.System.putInt(
5938 mContext.getContentResolver(),
5939 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5940
5941 synchronized (this) {
5942 mAlwaysFinishActivities = enabled;
5943 }
5944 }
5945
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005946 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005948 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005949 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005950 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005951 }
5952 }
5953
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005954 public boolean isUserAMonkey() {
5955 // For now the fact that there is a controller implies
5956 // we have a monkey.
5957 synchronized (this) {
5958 return mController != null;
5959 }
5960 }
5961
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005962 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005963 synchronized (this) {
5964 mWatchers.register(watcher);
5965 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005966 }
5967
5968 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005969 synchronized (this) {
5970 mWatchers.unregister(watcher);
5971 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005972 }
5973
Daniel Sandler69a48172010-06-23 16:29:36 -04005974 public void setImmersive(IBinder token, boolean immersive) {
5975 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005976 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005977 if (index < 0) {
5978 throw new IllegalArgumentException();
5979 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005980 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005981 r.immersive = immersive;
5982 }
5983 }
5984
5985 public boolean isImmersive(IBinder token) {
5986 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005987 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005988 if (index < 0) {
5989 throw new IllegalArgumentException();
5990 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005991 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005992 return r.immersive;
5993 }
5994 }
5995
5996 public boolean isTopActivityImmersive() {
5997 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005998 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005999 return (r != null) ? r.immersive : false;
6000 }
6001 }
6002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006003 public final void enterSafeMode() {
6004 synchronized(this) {
6005 // It only makes sense to do this before the system is ready
6006 // and started launching other packages.
6007 if (!mSystemReady) {
6008 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006009 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006010 } catch (RemoteException e) {
6011 }
6012
6013 View v = LayoutInflater.from(mContext).inflate(
6014 com.android.internal.R.layout.safe_mode, null);
6015 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown3b2b3542010-10-15 00:54:27 -07006016 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006017 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6018 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6019 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6020 lp.format = v.getBackground().getOpacity();
6021 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6022 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6023 ((WindowManager)mContext.getSystemService(
6024 Context.WINDOW_SERVICE)).addView(v, lp);
6025 }
6026 }
6027 }
6028
6029 public void noteWakeupAlarm(IIntentSender sender) {
6030 if (!(sender instanceof PendingIntentRecord)) {
6031 return;
6032 }
6033 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6034 synchronized (stats) {
6035 if (mBatteryStatsService.isOnBattery()) {
6036 mBatteryStatsService.enforceCallingPermission();
6037 PendingIntentRecord rec = (PendingIntentRecord)sender;
6038 int MY_UID = Binder.getCallingUid();
6039 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6040 BatteryStatsImpl.Uid.Pkg pkg =
6041 stats.getPackageStatsLocked(uid, rec.key.packageName);
6042 pkg.incWakeupsLocked();
6043 }
6044 }
6045 }
6046
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006047 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006049 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006050 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006051 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006052 // XXX Note: don't acquire main activity lock here, because the window
6053 // manager calls in with its locks held.
6054
6055 boolean killed = false;
6056 synchronized (mPidsSelfLocked) {
6057 int[] types = new int[pids.length];
6058 int worstType = 0;
6059 for (int i=0; i<pids.length; i++) {
6060 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6061 if (proc != null) {
6062 int type = proc.setAdj;
6063 types[i] = type;
6064 if (type > worstType) {
6065 worstType = type;
6066 }
6067 }
6068 }
6069
6070 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6071 // then constrain it so we will kill all hidden procs.
6072 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6073 worstType = HIDDEN_APP_MIN_ADJ;
6074 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006075 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006076 for (int i=0; i<pids.length; i++) {
6077 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6078 if (proc == null) {
6079 continue;
6080 }
6081 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006082 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006083 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006084 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6085 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006086 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006087 proc.killedBackground = true;
6088 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006089 }
6090 }
6091 }
6092 return killed;
6093 }
6094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006095 public final void startRunning(String pkg, String cls, String action,
6096 String data) {
6097 synchronized(this) {
6098 if (mStartRunning) {
6099 return;
6100 }
6101 mStartRunning = true;
6102 mTopComponent = pkg != null && cls != null
6103 ? new ComponentName(pkg, cls) : null;
6104 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6105 mTopData = data;
6106 if (!mSystemReady) {
6107 return;
6108 }
6109 }
6110
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006111 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006112 }
6113
6114 private void retrieveSettings() {
6115 final ContentResolver resolver = mContext.getContentResolver();
6116 String debugApp = Settings.System.getString(
6117 resolver, Settings.System.DEBUG_APP);
6118 boolean waitForDebugger = Settings.System.getInt(
6119 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6120 boolean alwaysFinishActivities = Settings.System.getInt(
6121 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6122
6123 Configuration configuration = new Configuration();
6124 Settings.System.getConfiguration(resolver, configuration);
6125
6126 synchronized (this) {
6127 mDebugApp = mOrigDebugApp = debugApp;
6128 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6129 mAlwaysFinishActivities = alwaysFinishActivities;
6130 // This happens before any activities are started, so we can
6131 // change mConfiguration in-place.
6132 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006133 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006134 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006135 }
6136 }
6137
6138 public boolean testIsSystemReady() {
6139 // no need to synchronize(this) just to read & return the value
6140 return mSystemReady;
6141 }
6142
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006143 private static File getCalledPreBootReceiversFile() {
6144 File dataDir = Environment.getDataDirectory();
6145 File systemDir = new File(dataDir, "system");
6146 File fname = new File(systemDir, "called_pre_boots.dat");
6147 return fname;
6148 }
6149
6150 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6151 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6152 File file = getCalledPreBootReceiversFile();
6153 FileInputStream fis = null;
6154 try {
6155 fis = new FileInputStream(file);
6156 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6157 int vers = dis.readInt();
6158 String codename = dis.readUTF();
6159 if (vers == android.os.Build.VERSION.SDK_INT
6160 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6161 int num = dis.readInt();
6162 while (num > 0) {
6163 num--;
6164 String pkg = dis.readUTF();
6165 String cls = dis.readUTF();
6166 lastDoneReceivers.add(new ComponentName(pkg, cls));
6167 }
6168 }
6169 } catch (FileNotFoundException e) {
6170 } catch (IOException e) {
6171 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6172 } finally {
6173 if (fis != null) {
6174 try {
6175 fis.close();
6176 } catch (IOException e) {
6177 }
6178 }
6179 }
6180 return lastDoneReceivers;
6181 }
6182
6183 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6184 File file = getCalledPreBootReceiversFile();
6185 FileOutputStream fos = null;
6186 DataOutputStream dos = null;
6187 try {
6188 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6189 fos = new FileOutputStream(file);
6190 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6191 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6192 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6193 dos.writeInt(list.size());
6194 for (int i=0; i<list.size(); i++) {
6195 dos.writeUTF(list.get(i).getPackageName());
6196 dos.writeUTF(list.get(i).getClassName());
6197 }
6198 } catch (IOException e) {
6199 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6200 file.delete();
6201 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006202 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006203 if (dos != null) {
6204 try {
6205 dos.close();
6206 } catch (IOException e) {
6207 // TODO Auto-generated catch block
6208 e.printStackTrace();
6209 }
6210 }
6211 }
6212 }
6213
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006214 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 // In the simulator, startRunning will never have been called, which
6216 // normally sets a few crucial variables. Do it here instead.
6217 if (!Process.supportsProcesses()) {
6218 mStartRunning = true;
6219 mTopAction = Intent.ACTION_MAIN;
6220 }
6221
6222 synchronized(this) {
6223 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006224 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006225 return;
6226 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006227
6228 // Check to see if there are any update receivers to run.
6229 if (!mDidUpdate) {
6230 if (mWaitingUpdate) {
6231 return;
6232 }
6233 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6234 List<ResolveInfo> ris = null;
6235 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006236 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006237 intent, null, 0);
6238 } catch (RemoteException e) {
6239 }
6240 if (ris != null) {
6241 for (int i=ris.size()-1; i>=0; i--) {
6242 if ((ris.get(i).activityInfo.applicationInfo.flags
6243 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6244 ris.remove(i);
6245 }
6246 }
6247 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006248
6249 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6250
6251 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006252 for (int i=0; i<ris.size(); i++) {
6253 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006254 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6255 if (lastDoneReceivers.contains(comp)) {
6256 ris.remove(i);
6257 i--;
6258 }
6259 }
6260
6261 for (int i=0; i<ris.size(); i++) {
6262 ActivityInfo ai = ris.get(i).activityInfo;
6263 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6264 doneReceivers.add(comp);
6265 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006266 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006267 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006268 finisher = new IIntentReceiver.Stub() {
6269 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006270 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006271 boolean sticky) {
6272 // The raw IIntentReceiver interface is called
6273 // with the AM lock held, so redispatch to
6274 // execute our code without the lock.
6275 mHandler.post(new Runnable() {
6276 public void run() {
6277 synchronized (ActivityManagerService.this) {
6278 mDidUpdate = true;
6279 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006280 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006281 systemReady(goingCallback);
6282 }
6283 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006284 }
6285 };
6286 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006287 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006288 broadcastIntentLocked(null, null, intent, null, finisher,
6289 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006290 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006291 mWaitingUpdate = true;
6292 }
6293 }
6294 }
6295 if (mWaitingUpdate) {
6296 return;
6297 }
6298 mDidUpdate = true;
6299 }
6300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006301 mSystemReady = true;
6302 if (!mStartRunning) {
6303 return;
6304 }
6305 }
6306
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006307 ArrayList<ProcessRecord> procsToKill = null;
6308 synchronized(mPidsSelfLocked) {
6309 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6310 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6311 if (!isAllowedWhileBooting(proc.info)){
6312 if (procsToKill == null) {
6313 procsToKill = new ArrayList<ProcessRecord>();
6314 }
6315 procsToKill.add(proc);
6316 }
6317 }
6318 }
6319
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006320 synchronized(this) {
6321 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006322 for (int i=procsToKill.size()-1; i>=0; i--) {
6323 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006324 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006325 removeProcessLocked(proc, true);
6326 }
6327 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006328
6329 // Now that we have cleaned up any update processes, we
6330 // are ready to start launching real processes and know that
6331 // we won't trample on them any more.
6332 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006333 }
6334
Joe Onorato8a9b2202010-02-26 18:56:32 -08006335 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006336 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006337 SystemClock.uptimeMillis());
6338
6339 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006340 // Make sure we have no pre-ready processes sitting around.
6341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6343 ResolveInfo ri = mContext.getPackageManager()
6344 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006345 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 CharSequence errorMsg = null;
6347 if (ri != null) {
6348 ActivityInfo ai = ri.activityInfo;
6349 ApplicationInfo app = ai.applicationInfo;
6350 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6351 mTopAction = Intent.ACTION_FACTORY_TEST;
6352 mTopData = null;
6353 mTopComponent = new ComponentName(app.packageName,
6354 ai.name);
6355 } else {
6356 errorMsg = mContext.getResources().getText(
6357 com.android.internal.R.string.factorytest_not_system);
6358 }
6359 } else {
6360 errorMsg = mContext.getResources().getText(
6361 com.android.internal.R.string.factorytest_no_action);
6362 }
6363 if (errorMsg != null) {
6364 mTopAction = null;
6365 mTopData = null;
6366 mTopComponent = null;
6367 Message msg = Message.obtain();
6368 msg.what = SHOW_FACTORY_ERROR_MSG;
6369 msg.getData().putCharSequence("msg", errorMsg);
6370 mHandler.sendMessage(msg);
6371 }
6372 }
6373 }
6374
6375 retrieveSettings();
6376
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006377 if (goingCallback != null) goingCallback.run();
6378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006379 synchronized (this) {
6380 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6381 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006382 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006383 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 if (apps != null) {
6385 int N = apps.size();
6386 int i;
6387 for (i=0; i<N; i++) {
6388 ApplicationInfo info
6389 = (ApplicationInfo)apps.get(i);
6390 if (info != null &&
6391 !info.packageName.equals("android")) {
6392 addAppLocked(info);
6393 }
6394 }
6395 }
6396 } catch (RemoteException ex) {
6397 // pm is in same process, this will never happen.
6398 }
6399 }
6400
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006401 // Start up initial activity.
6402 mBooting = true;
6403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006404 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006405 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006406 Message msg = Message.obtain();
6407 msg.what = SHOW_UID_ERROR_MSG;
6408 mHandler.sendMessage(msg);
6409 }
6410 } catch (RemoteException e) {
6411 }
6412
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006413 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006414 }
6415 }
6416
Dan Egnorb7f03672009-12-09 16:22:32 -08006417 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006418 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006419 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006420 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006421 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006422 startAppProblemLocked(app);
6423 app.stopFreezingAllLocked();
6424 return handleAppCrashLocked(app);
6425 }
6426
Dan Egnorb7f03672009-12-09 16:22:32 -08006427 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006428 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006429 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006430 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006431 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6432 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006433 startAppProblemLocked(app);
6434 app.stopFreezingAllLocked();
6435 }
6436
6437 /**
6438 * Generate a process error record, suitable for attachment to a ProcessRecord.
6439 *
6440 * @param app The ProcessRecord in which the error occurred.
6441 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6442 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006443 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006444 * @param shortMsg Short message describing the crash.
6445 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006446 * @param stackTrace Full crash stack trace, may be null.
6447 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006448 * @return Returns a fully-formed AppErrorStateInfo record.
6449 */
6450 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006451 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006452 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006454 report.condition = condition;
6455 report.processName = app.processName;
6456 report.pid = app.pid;
6457 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006458 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006459 report.shortMsg = shortMsg;
6460 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006461 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006462
6463 return report;
6464 }
6465
Dan Egnor42471dd2010-01-07 17:25:22 -08006466 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 synchronized (this) {
6468 app.crashing = false;
6469 app.crashingReport = null;
6470 app.notResponding = false;
6471 app.notRespondingReport = null;
6472 if (app.anrDialog == fromDialog) {
6473 app.anrDialog = null;
6474 }
6475 if (app.waitDialog == fromDialog) {
6476 app.waitDialog = null;
6477 }
6478 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006479 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006480 Slog.i(ActivityManagerService.TAG, "Killing "
6481 + app.processName + " (pid=" + app.pid + "): user's request");
6482 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6483 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006484 Process.killProcess(app.pid);
6485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 }
6487 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006488
Dan Egnorb7f03672009-12-09 16:22:32 -08006489 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006490 long now = SystemClock.uptimeMillis();
6491
6492 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6493 app.info.uid);
6494 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6495 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006496 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006497 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006498 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006499 app.info.processName, app.info.uid);
6500 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006501 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6502 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006503 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006504 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006505 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006506 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006507 }
6508 }
6509 if (!app.persistent) {
6510 // We don't want to start this process again until the user
6511 // explicitly does so... but for persistent process, we really
6512 // need to keep it running. If a persistent process is actually
6513 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006514 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 app.info.processName);
6516 mBadProcesses.put(app.info.processName, app.info.uid, now);
6517 app.bad = true;
6518 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6519 app.removed = true;
6520 removeProcessLocked(app, false);
6521 return false;
6522 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006523 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006524 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006525 if (r.app == app) {
6526 // If the top running activity is from this crashing
6527 // process, then terminate it to avoid getting in a loop.
6528 Slog.w(TAG, " Force finishing activity "
6529 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006530 int index = mMainStack.indexOfTokenLocked(r);
6531 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006532 Activity.RESULT_CANCELED, null, "crashed");
6533 // Also terminate an activities below it that aren't yet
6534 // stopped, to avoid a situation where one will get
6535 // re-start our crashing activity once it gets resumed again.
6536 index--;
6537 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006538 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006539 if (r.state == ActivityState.RESUMED
6540 || r.state == ActivityState.PAUSING
6541 || r.state == ActivityState.PAUSED) {
6542 if (!r.isHomeActivity) {
6543 Slog.w(TAG, " Force finishing activity "
6544 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006545 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006546 Activity.RESULT_CANCELED, null, "crashed");
6547 }
6548 }
6549 }
6550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006551 }
6552
6553 // Bump up the crash count of any services currently running in the proc.
6554 if (app.services.size() != 0) {
6555 // Any services running in the application need to be placed
6556 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006557 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006558 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006559 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006560 sr.crashCount++;
6561 }
6562 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006563
6564 // If the crashing process is what we consider to be the "home process" and it has been
6565 // replaced by a third-party app, clear the package preferred activities from packages
6566 // with a home activity running in the process to prevent a repeatedly crashing app
6567 // from blocking the user to manually clear the list.
6568 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6569 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6570 Iterator it = mHomeProcess.activities.iterator();
6571 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006572 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006573 if (r.isHomeActivity) {
6574 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6575 try {
6576 ActivityThread.getPackageManager()
6577 .clearPackagePreferredActivities(r.packageName);
6578 } catch (RemoteException c) {
6579 // pm is in same process, this will never happen.
6580 }
6581 }
6582 }
6583 }
6584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006585 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6586 return true;
6587 }
6588
6589 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006590 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6591 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006592 skipCurrentReceiverLocked(app);
6593 }
6594
6595 void skipCurrentReceiverLocked(ProcessRecord app) {
6596 boolean reschedule = false;
6597 BroadcastRecord r = app.curReceiver;
6598 if (r != null) {
6599 // The current broadcast is waiting for this app's receiver
6600 // to be finished. Looks like that's not going to happen, so
6601 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006602 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006603 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6604 r.resultExtras, r.resultAbort, true);
6605 reschedule = true;
6606 }
6607 r = mPendingBroadcast;
6608 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006609 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006610 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006611 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006612 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6613 r.resultExtras, r.resultAbort, true);
6614 reschedule = true;
6615 }
6616 if (reschedule) {
6617 scheduleBroadcastsLocked();
6618 }
6619 }
6620
Dan Egnor60d87622009-12-16 16:32:58 -08006621 /**
6622 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6623 * The application process will exit immediately after this call returns.
6624 * @param app object of the crashing app, null for the system server
6625 * @param crashInfo describing the exception
6626 */
6627 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6628 ProcessRecord r = findAppProcess(app);
6629
6630 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6631 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006632 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006633 crashInfo.exceptionClassName,
6634 crashInfo.exceptionMessage,
6635 crashInfo.throwFileName,
6636 crashInfo.throwLineNumber);
6637
Dan Egnor42471dd2010-01-07 17:25:22 -08006638 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006639
6640 crashApplication(r, crashInfo);
6641 }
6642
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006643 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006644 IBinder app,
6645 int violationMask,
6646 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006647 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006648
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006649 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006650 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006651 boolean logIt = true;
6652 synchronized (mAlreadyLoggedViolatedStacks) {
6653 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6654 logIt = false;
6655 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006656 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006657 // the relative pain numbers, without logging all
6658 // the stack traces repeatedly. We'd want to do
6659 // likewise in the client code, which also does
6660 // dup suppression, before the Binder call.
6661 } else {
6662 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6663 mAlreadyLoggedViolatedStacks.clear();
6664 }
6665 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6666 }
6667 }
6668 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006669 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006670 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006671 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006672
6673 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6674 AppErrorResult result = new AppErrorResult();
6675 synchronized (this) {
6676 final long origId = Binder.clearCallingIdentity();
6677
6678 Message msg = Message.obtain();
6679 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6680 HashMap<String, Object> data = new HashMap<String, Object>();
6681 data.put("result", result);
6682 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006683 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006684 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006685 msg.obj = data;
6686 mHandler.sendMessage(msg);
6687
6688 Binder.restoreCallingIdentity(origId);
6689 }
6690 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006691 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006692 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006693 }
6694
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006695 // Depending on the policy in effect, there could be a bunch of
6696 // these in quick succession so we try to batch these together to
6697 // minimize disk writes, number of dropbox entries, and maximize
6698 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006699 private void logStrictModeViolationToDropBox(
6700 ProcessRecord process,
6701 StrictMode.ViolationInfo info) {
6702 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006703 return;
6704 }
6705 final boolean isSystemApp = process == null ||
6706 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6707 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6708 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6709 final DropBoxManager dbox = (DropBoxManager)
6710 mContext.getSystemService(Context.DROPBOX_SERVICE);
6711
6712 // Exit early if the dropbox isn't configured to accept this report type.
6713 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6714
6715 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006716 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006717 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6718 synchronized (sb) {
6719 bufferWasEmpty = sb.length() == 0;
6720 appendDropBoxProcessHeaders(process, sb);
6721 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6722 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006723 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6724 if (info.violationNumThisLoop != 0) {
6725 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6726 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006727 if (info.numAnimationsRunning != 0) {
6728 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6729 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006730 if (info.broadcastIntentAction != null) {
6731 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6732 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006733 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006734 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006735 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006736 if (info.tags != null) {
6737 for (String tag : info.tags) {
6738 sb.append("Span-Tag: ").append(tag).append("\n");
6739 }
6740 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006741 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006742 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6743 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006744 }
6745 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006746
6747 // Only buffer up to ~64k. Various logging bits truncate
6748 // things at 128k.
6749 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006750 }
6751
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006752 // Flush immediately if the buffer's grown too large, or this
6753 // is a non-system app. Non-system apps are isolated with a
6754 // different tag & policy and not batched.
6755 //
6756 // Batching is useful during internal testing with
6757 // StrictMode settings turned up high. Without batching,
6758 // thousands of separate files could be created on boot.
6759 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006760 new Thread("Error dump: " + dropboxTag) {
6761 @Override
6762 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006763 String report;
6764 synchronized (sb) {
6765 report = sb.toString();
6766 sb.delete(0, sb.length());
6767 sb.trimToSize();
6768 }
6769 if (report.length() != 0) {
6770 dbox.addText(dropboxTag, report);
6771 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006772 }
6773 }.start();
6774 return;
6775 }
6776
6777 // System app batching:
6778 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006779 // An existing dropbox-writing thread is outstanding, so
6780 // we don't need to start it up. The existing thread will
6781 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006782 return;
6783 }
6784
6785 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6786 // (After this point, we shouldn't access AMS internal data structures.)
6787 new Thread("Error dump: " + dropboxTag) {
6788 @Override
6789 public void run() {
6790 // 5 second sleep to let stacks arrive and be batched together
6791 try {
6792 Thread.sleep(5000); // 5 seconds
6793 } catch (InterruptedException e) {}
6794
6795 String errorReport;
6796 synchronized (mStrictModeBuffer) {
6797 errorReport = mStrictModeBuffer.toString();
6798 if (errorReport.length() == 0) {
6799 return;
6800 }
6801 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6802 mStrictModeBuffer.trimToSize();
6803 }
6804 dbox.addText(dropboxTag, errorReport);
6805 }
6806 }.start();
6807 }
6808
Dan Egnor60d87622009-12-16 16:32:58 -08006809 /**
6810 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6811 * @param app object of the crashing app, null for the system server
6812 * @param tag reported by the caller
6813 * @param crashInfo describing the context of the error
6814 * @return true if the process should exit immediately (WTF is fatal)
6815 */
6816 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006817 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006818 ProcessRecord r = findAppProcess(app);
6819
6820 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6821 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006822 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006823 tag, crashInfo.exceptionMessage);
6824
Dan Egnor42471dd2010-01-07 17:25:22 -08006825 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006826
Doug Zongker43866e02010-01-07 12:09:54 -08006827 if (Settings.Secure.getInt(mContext.getContentResolver(),
6828 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006829 crashApplication(r, crashInfo);
6830 return true;
6831 } else {
6832 return false;
6833 }
6834 }
6835
6836 /**
6837 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6838 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6839 */
6840 private ProcessRecord findAppProcess(IBinder app) {
6841 if (app == null) {
6842 return null;
6843 }
6844
6845 synchronized (this) {
6846 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6847 final int NA = apps.size();
6848 for (int ia=0; ia<NA; ia++) {
6849 ProcessRecord p = apps.valueAt(ia);
6850 if (p.thread != null && p.thread.asBinder() == app) {
6851 return p;
6852 }
6853 }
6854 }
6855
Joe Onorato8a9b2202010-02-26 18:56:32 -08006856 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006857 return null;
6858 }
6859 }
6860
6861 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006862 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6863 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006864 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006865 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6866 // Note: ProcessRecord 'process' is guarded by the service
6867 // instance. (notably process.pkgList, which could otherwise change
6868 // concurrently during execution of this method)
6869 synchronized (this) {
6870 if (process == null || process.pid == MY_PID) {
6871 sb.append("Process: system_server\n");
6872 } else {
6873 sb.append("Process: ").append(process.processName).append("\n");
6874 }
6875 if (process == null) {
6876 return;
6877 }
Dan Egnora455d192010-03-12 08:52:28 -08006878 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006879 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006880 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6881 for (String pkg : process.pkgList) {
6882 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006883 try {
Dan Egnora455d192010-03-12 08:52:28 -08006884 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6885 if (pi != null) {
6886 sb.append(" v").append(pi.versionCode);
6887 if (pi.versionName != null) {
6888 sb.append(" (").append(pi.versionName).append(")");
6889 }
6890 }
6891 } catch (RemoteException e) {
6892 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006893 }
Dan Egnora455d192010-03-12 08:52:28 -08006894 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006895 }
Dan Egnora455d192010-03-12 08:52:28 -08006896 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006897 }
6898
6899 private static String processClass(ProcessRecord process) {
6900 if (process == null || process.pid == MY_PID) {
6901 return "system_server";
6902 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6903 return "system_app";
6904 } else {
6905 return "data_app";
6906 }
6907 }
6908
6909 /**
6910 * Write a description of an error (crash, WTF, ANR) to the drop box.
6911 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6912 * @param process which caused the error, null means the system server
6913 * @param activity which triggered the error, null if unknown
6914 * @param parent activity related to the error, null if unknown
6915 * @param subject line related to the error, null if absent
6916 * @param report in long form describing the error, null if absent
6917 * @param logFile to include in the report, null if none
6918 * @param crashInfo giving an application stack trace, null if absent
6919 */
6920 public void addErrorToDropBox(String eventType,
6921 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6922 final String report, final File logFile,
6923 final ApplicationErrorReport.CrashInfo crashInfo) {
6924 // NOTE -- this must never acquire the ActivityManagerService lock,
6925 // otherwise the watchdog may be prevented from resetting the system.
6926
6927 final String dropboxTag = processClass(process) + "_" + eventType;
6928 final DropBoxManager dbox = (DropBoxManager)
6929 mContext.getSystemService(Context.DROPBOX_SERVICE);
6930
6931 // Exit early if the dropbox isn't configured to accept this report type.
6932 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6933
6934 final StringBuilder sb = new StringBuilder(1024);
6935 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006936 if (activity != null) {
6937 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6938 }
6939 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6940 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6941 }
6942 if (parent != null && parent != activity) {
6943 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6944 }
6945 if (subject != null) {
6946 sb.append("Subject: ").append(subject).append("\n");
6947 }
6948 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02006949 if (Debug.isDebuggerConnected()) {
6950 sb.append("Debugger: Connected\n");
6951 }
Dan Egnora455d192010-03-12 08:52:28 -08006952 sb.append("\n");
6953
6954 // Do the rest in a worker thread to avoid blocking the caller on I/O
6955 // (After this point, we shouldn't access AMS internal data structures.)
6956 Thread worker = new Thread("Error dump: " + dropboxTag) {
6957 @Override
6958 public void run() {
6959 if (report != null) {
6960 sb.append(report);
6961 }
6962 if (logFile != null) {
6963 try {
6964 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6965 } catch (IOException e) {
6966 Slog.e(TAG, "Error reading " + logFile, e);
6967 }
6968 }
6969 if (crashInfo != null && crashInfo.stackTrace != null) {
6970 sb.append(crashInfo.stackTrace);
6971 }
6972
6973 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6974 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6975 if (lines > 0) {
6976 sb.append("\n");
6977
6978 // Merge several logcat streams, and take the last N lines
6979 InputStreamReader input = null;
6980 try {
6981 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6982 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6983 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6984
6985 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6986 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6987 input = new InputStreamReader(logcat.getInputStream());
6988
6989 int num;
6990 char[] buf = new char[8192];
6991 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6992 } catch (IOException e) {
6993 Slog.e(TAG, "Error running logcat", e);
6994 } finally {
6995 if (input != null) try { input.close(); } catch (IOException e) {}
6996 }
6997 }
6998
6999 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007000 }
Dan Egnora455d192010-03-12 08:52:28 -08007001 };
7002
7003 if (process == null || process.pid == MY_PID) {
7004 worker.run(); // We may be about to die -- need to run this synchronously
7005 } else {
7006 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007007 }
7008 }
7009
7010 /**
7011 * Bring up the "unexpected error" dialog box for a crashing app.
7012 * Deal with edge cases (intercepts from instrumented applications,
7013 * ActivityController, error intent receivers, that sort of thing).
7014 * @param r the application crashing
7015 * @param crashInfo describing the failure
7016 */
7017 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007018 long timeMillis = System.currentTimeMillis();
7019 String shortMsg = crashInfo.exceptionClassName;
7020 String longMsg = crashInfo.exceptionMessage;
7021 String stackTrace = crashInfo.stackTrace;
7022 if (shortMsg != null && longMsg != null) {
7023 longMsg = shortMsg + ": " + longMsg;
7024 } else if (shortMsg != null) {
7025 longMsg = shortMsg;
7026 }
7027
Dan Egnor60d87622009-12-16 16:32:58 -08007028 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007029 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007030 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007031 try {
7032 String name = r != null ? r.processName : null;
7033 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007034 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007035 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007036 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007037 + " at watcher's request");
7038 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007039 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007040 }
7041 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007042 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007043 }
7044 }
7045
7046 final long origId = Binder.clearCallingIdentity();
7047
7048 // If this process is running instrumentation, finish it.
7049 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007050 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007051 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007052 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7053 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007054 Bundle info = new Bundle();
7055 info.putString("shortMsg", shortMsg);
7056 info.putString("longMsg", longMsg);
7057 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7058 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007059 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060 }
7061
Dan Egnor60d87622009-12-16 16:32:58 -08007062 // If we can't identify the process or it's already exceeded its crash quota,
7063 // quit right away without showing a crash dialog.
7064 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007065 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007066 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007067 }
7068
7069 Message msg = Message.obtain();
7070 msg.what = SHOW_ERROR_MSG;
7071 HashMap data = new HashMap();
7072 data.put("result", result);
7073 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007074 msg.obj = data;
7075 mHandler.sendMessage(msg);
7076
7077 Binder.restoreCallingIdentity(origId);
7078 }
7079
7080 int res = result.get();
7081
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007082 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007083 synchronized (this) {
7084 if (r != null) {
7085 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7086 SystemClock.uptimeMillis());
7087 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007088 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007089 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007090 }
7091 }
7092
7093 if (appErrorIntent != null) {
7094 try {
7095 mContext.startActivity(appErrorIntent);
7096 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007097 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007100 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007101
7102 Intent createAppErrorIntentLocked(ProcessRecord r,
7103 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7104 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007105 if (report == null) {
7106 return null;
7107 }
7108 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7109 result.setComponent(r.errorReportReceiver);
7110 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7111 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7112 return result;
7113 }
7114
Dan Egnorb7f03672009-12-09 16:22:32 -08007115 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7116 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007117 if (r.errorReportReceiver == null) {
7118 return null;
7119 }
7120
7121 if (!r.crashing && !r.notResponding) {
7122 return null;
7123 }
7124
Dan Egnorb7f03672009-12-09 16:22:32 -08007125 ApplicationErrorReport report = new ApplicationErrorReport();
7126 report.packageName = r.info.packageName;
7127 report.installerPackageName = r.errorReportReceiver.getPackageName();
7128 report.processName = r.processName;
7129 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007130 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007131
Dan Egnorb7f03672009-12-09 16:22:32 -08007132 if (r.crashing) {
7133 report.type = ApplicationErrorReport.TYPE_CRASH;
7134 report.crashInfo = crashInfo;
7135 } else if (r.notResponding) {
7136 report.type = ApplicationErrorReport.TYPE_ANR;
7137 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007138
Dan Egnorb7f03672009-12-09 16:22:32 -08007139 report.anrInfo.activity = r.notRespondingReport.tag;
7140 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7141 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007142 }
7143
Dan Egnorb7f03672009-12-09 16:22:32 -08007144 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007145 }
7146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007147 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7148 // assume our apps are happy - lazy create the list
7149 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7150
7151 synchronized (this) {
7152
7153 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007154 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7155 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007156 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7157 // This one's in trouble, so we'll generate a report for it
7158 // crashes are higher priority (in case there's a crash *and* an anr)
7159 ActivityManager.ProcessErrorStateInfo report = null;
7160 if (app.crashing) {
7161 report = app.crashingReport;
7162 } else if (app.notResponding) {
7163 report = app.notRespondingReport;
7164 }
7165
7166 if (report != null) {
7167 if (errList == null) {
7168 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7169 }
7170 errList.add(report);
7171 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007172 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007173 " crashing = " + app.crashing +
7174 " notResponding = " + app.notResponding);
7175 }
7176 }
7177 }
7178 }
7179
7180 return errList;
7181 }
7182
7183 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7184 // Lazy instantiation of list
7185 List<ActivityManager.RunningAppProcessInfo> runList = null;
7186 synchronized (this) {
7187 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007188 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7189 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007190 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7191 // Generate process state info for running application
7192 ActivityManager.RunningAppProcessInfo currApp =
7193 new ActivityManager.RunningAppProcessInfo(app.processName,
7194 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007195 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007196 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007197 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007198 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007199 if (app.persistent) {
7200 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007202 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007203 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007204 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7205 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7206 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007207 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7208 } else if (adj >= HOME_APP_ADJ) {
7209 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7210 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007211 } else if (adj >= SECONDARY_SERVER_ADJ) {
7212 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007213 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007214 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007215 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7216 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007217 } else if (adj >= VISIBLE_APP_ADJ) {
7218 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7219 } else {
7220 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7221 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007222 currApp.importanceReasonCode = app.adjTypeCode;
7223 if (app.adjSource instanceof ProcessRecord) {
7224 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007225 } else if (app.adjSource instanceof ActivityRecord) {
7226 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007227 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7228 }
7229 if (app.adjTarget instanceof ComponentName) {
7230 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7231 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007232 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007233 // + " lru=" + currApp.lru);
7234 if (runList == null) {
7235 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7236 }
7237 runList.add(currApp);
7238 }
7239 }
7240 }
7241 return runList;
7242 }
7243
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007244 public List<ApplicationInfo> getRunningExternalApplications() {
7245 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7246 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7247 if (runningApps != null && runningApps.size() > 0) {
7248 Set<String> extList = new HashSet<String>();
7249 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7250 if (app.pkgList != null) {
7251 for (String pkg : app.pkgList) {
7252 extList.add(pkg);
7253 }
7254 }
7255 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007256 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007257 for (String pkg : extList) {
7258 try {
7259 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7260 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7261 retList.add(info);
7262 }
7263 } catch (RemoteException e) {
7264 }
7265 }
7266 }
7267 return retList;
7268 }
7269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007270 @Override
7271 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007272 if (checkCallingPermission(android.Manifest.permission.DUMP)
7273 != PackageManager.PERMISSION_GRANTED) {
7274 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7275 + Binder.getCallingPid()
7276 + ", uid=" + Binder.getCallingUid()
7277 + " without permission "
7278 + android.Manifest.permission.DUMP);
7279 return;
7280 }
7281
7282 boolean dumpAll = false;
7283
7284 int opti = 0;
7285 while (opti < args.length) {
7286 String opt = args[opti];
7287 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7288 break;
7289 }
7290 opti++;
7291 if ("-a".equals(opt)) {
7292 dumpAll = true;
7293 } else if ("-h".equals(opt)) {
7294 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007295 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007296 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007297 pw.println(" a[ctivities]: activity stack state");
7298 pw.println(" b[roadcasts]: broadcast state");
7299 pw.println(" i[ntents]: pending intent state");
7300 pw.println(" p[rocesses]: process state");
7301 pw.println(" o[om]: out of memory management");
7302 pw.println(" prov[iders]: content provider state");
7303 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007304 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007305 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007306 } else {
7307 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007309 }
7310
7311 // Is the caller requesting to dump a particular piece of data?
7312 if (opti < args.length) {
7313 String cmd = args[opti];
7314 opti++;
7315 if ("activities".equals(cmd) || "a".equals(cmd)) {
7316 synchronized (this) {
7317 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007318 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007319 return;
7320 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7321 synchronized (this) {
7322 dumpBroadcastsLocked(fd, pw, args, opti, true);
7323 }
7324 return;
7325 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7326 synchronized (this) {
7327 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7328 }
7329 return;
7330 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7331 synchronized (this) {
7332 dumpProcessesLocked(fd, pw, args, opti, true);
7333 }
7334 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007335 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7336 synchronized (this) {
7337 dumpOomLocked(fd, pw, args, opti, true);
7338 }
7339 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007340 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7341 synchronized (this) {
7342 dumpProvidersLocked(fd, pw, args, opti, true);
7343 }
7344 return;
7345 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007346 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007347 return;
7348 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7349 synchronized (this) {
7350 dumpServicesLocked(fd, pw, args, opti, true);
7351 }
7352 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007353 } else {
7354 // Dumping a single activity?
7355 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7356 return;
7357 }
7358 pw.println("Bad activity command: " + cmd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007359 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007360 }
7361
7362 // No piece of data specified, dump everything.
7363 synchronized (this) {
7364 boolean needSep;
7365 if (dumpAll) {
7366 pw.println("Providers in Current Activity Manager State:");
7367 }
7368 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7369 if (needSep) {
7370 pw.println(" ");
7371 }
7372 if (dumpAll) {
7373 pw.println("-------------------------------------------------------------------------------");
7374 pw.println("Broadcasts in Current Activity Manager State:");
7375 }
7376 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7377 if (needSep) {
7378 pw.println(" ");
7379 }
7380 if (dumpAll) {
7381 pw.println("-------------------------------------------------------------------------------");
7382 pw.println("Services in Current Activity Manager State:");
7383 }
7384 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7385 if (needSep) {
7386 pw.println(" ");
7387 }
7388 if (dumpAll) {
7389 pw.println("-------------------------------------------------------------------------------");
7390 pw.println("PendingIntents in Current Activity Manager State:");
7391 }
7392 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7393 if (needSep) {
7394 pw.println(" ");
7395 }
7396 if (dumpAll) {
7397 pw.println("-------------------------------------------------------------------------------");
7398 pw.println("Activities in Current Activity Manager State:");
7399 }
7400 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7401 if (needSep) {
7402 pw.println(" ");
7403 }
7404 if (dumpAll) {
7405 pw.println("-------------------------------------------------------------------------------");
7406 pw.println("Processes in Current Activity Manager State:");
7407 }
7408 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7409 }
7410 }
7411
7412 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7413 int opti, boolean dumpAll, boolean needHeader) {
7414 if (needHeader) {
7415 pw.println(" Activity stack:");
7416 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007417 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007418 pw.println(" ");
7419 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007420 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7421 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007422 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007423 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007424 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007425 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007426 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007428 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007429 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007430 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007431 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007432 pw.println(" ");
7433 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007434 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007437 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007438 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7439 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007440 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007441 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007442
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007443 if (dumpAll && mRecentTasks.size() > 0) {
7444 pw.println(" ");
7445 pw.println("Recent tasks in Current Activity Manager State:");
7446
7447 final int N = mRecentTasks.size();
7448 for (int i=0; i<N; i++) {
7449 TaskRecord tr = mRecentTasks.get(i);
7450 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7451 pw.println(tr);
7452 mRecentTasks.get(i).dump(pw, " ");
7453 }
7454 }
7455
7456 pw.println(" ");
7457 pw.println(" mCurTask: " + mCurTask);
7458
7459 return true;
7460 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007461
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007462 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7463 int opti, boolean dumpAll) {
7464 boolean needSep = false;
7465 int numPers = 0;
7466
7467 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007468 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7469 final int NA = procs.size();
7470 for (int ia=0; ia<NA; ia++) {
7471 if (!needSep) {
7472 pw.println(" All known processes:");
7473 needSep = true;
7474 }
7475 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007476 pw.print(r.persistent ? " *PERS*" : " *APP*");
7477 pw.print(" UID "); pw.print(procs.keyAt(ia));
7478 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007479 r.dump(pw, " ");
7480 if (r.persistent) {
7481 numPers++;
7482 }
7483 }
7484 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007485 }
7486
7487 if (mLruProcesses.size() > 0) {
7488 if (needSep) pw.println(" ");
7489 needSep = true;
7490 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007491 dumpProcessOomList(pw, this, mLruProcesses, " ",
7492 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007493 needSep = true;
7494 }
7495
7496 synchronized (mPidsSelfLocked) {
7497 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007498 if (needSep) pw.println(" ");
7499 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007500 pw.println(" PID mappings:");
7501 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7502 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7503 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007504 }
7505 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007506 }
7507
7508 if (mForegroundProcesses.size() > 0) {
7509 if (needSep) pw.println(" ");
7510 needSep = true;
7511 pw.println(" Foreground Processes:");
7512 for (int i=0; i<mForegroundProcesses.size(); i++) {
7513 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7514 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007516 }
7517
7518 if (mPersistentStartingProcesses.size() > 0) {
7519 if (needSep) pw.println(" ");
7520 needSep = true;
7521 pw.println(" Persisent processes that are starting:");
7522 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007523 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007524 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007525
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007526 if (mStartingProcesses.size() > 0) {
7527 if (needSep) pw.println(" ");
7528 needSep = true;
7529 pw.println(" Processes that are starting:");
7530 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007531 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007533
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007534 if (mRemovedProcesses.size() > 0) {
7535 if (needSep) pw.println(" ");
7536 needSep = true;
7537 pw.println(" Processes that are being removed:");
7538 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007539 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007540 }
7541
7542 if (mProcessesOnHold.size() > 0) {
7543 if (needSep) pw.println(" ");
7544 needSep = true;
7545 pw.println(" Processes that are on old until the system is ready:");
7546 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007547 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549
Dianne Hackborn287952c2010-09-22 22:34:31 -07007550 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007551
7552 if (mProcessCrashTimes.getMap().size() > 0) {
7553 if (needSep) pw.println(" ");
7554 needSep = true;
7555 pw.println(" Time since processes crashed:");
7556 long now = SystemClock.uptimeMillis();
7557 for (Map.Entry<String, SparseArray<Long>> procs
7558 : mProcessCrashTimes.getMap().entrySet()) {
7559 SparseArray<Long> uids = procs.getValue();
7560 final int N = uids.size();
7561 for (int i=0; i<N; i++) {
7562 pw.print(" Process "); pw.print(procs.getKey());
7563 pw.print(" uid "); pw.print(uids.keyAt(i));
7564 pw.print(": last crashed ");
7565 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007566 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007567 }
7568 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007571 if (mBadProcesses.getMap().size() > 0) {
7572 if (needSep) pw.println(" ");
7573 needSep = true;
7574 pw.println(" Bad processes:");
7575 for (Map.Entry<String, SparseArray<Long>> procs
7576 : mBadProcesses.getMap().entrySet()) {
7577 SparseArray<Long> uids = procs.getValue();
7578 final int N = uids.size();
7579 for (int i=0; i<N; i++) {
7580 pw.print(" Bad process "); pw.print(procs.getKey());
7581 pw.print(" uid "); pw.print(uids.keyAt(i));
7582 pw.print(": crashed at time ");
7583 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007584 }
7585 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007587
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007588 pw.println(" ");
7589 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007590 if (mHeavyWeightProcess != null) {
7591 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7592 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007593 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007594 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007595 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7596 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7597 || mOrigWaitForDebugger) {
7598 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7599 + " mDebugTransient=" + mDebugTransient
7600 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7601 }
7602 if (mAlwaysFinishActivities || mController != null) {
7603 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7604 + " mController=" + mController);
7605 }
7606 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007607 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007608 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007609 + " mProcessesReady=" + mProcessesReady
7610 + " mSystemReady=" + mSystemReady);
7611 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007612 + " mBooted=" + mBooted
7613 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007614 pw.print(" mLastPowerCheckRealtime=");
7615 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7616 pw.println("");
7617 pw.print(" mLastPowerCheckUptime=");
7618 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7619 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007620 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7621 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007622 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007623 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007624
7625 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007626 }
7627
Dianne Hackborn287952c2010-09-22 22:34:31 -07007628 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7629 int opti, boolean needSep, boolean dumpAll) {
7630 if (mProcessesToGc.size() > 0) {
7631 if (needSep) pw.println(" ");
7632 needSep = true;
7633 pw.println(" Processes that are waiting to GC:");
7634 long now = SystemClock.uptimeMillis();
7635 for (int i=0; i<mProcessesToGc.size(); i++) {
7636 ProcessRecord proc = mProcessesToGc.get(i);
7637 pw.print(" Process "); pw.println(proc);
7638 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7639 pw.print(", last gced=");
7640 pw.print(now-proc.lastRequestedGc);
7641 pw.print(" ms ago, last lowMem=");
7642 pw.print(now-proc.lastLowMemory);
7643 pw.println(" ms ago");
7644
7645 }
7646 }
7647 return needSep;
7648 }
7649
7650 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7651 int opti, boolean dumpAll) {
7652 boolean needSep = false;
7653
7654 if (mLruProcesses.size() > 0) {
7655 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7656
7657 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7658 @Override
7659 public int compare(ProcessRecord object1, ProcessRecord object2) {
7660 if (object1.setAdj != object2.setAdj) {
7661 return object1.setAdj > object2.setAdj ? -1 : 1;
7662 }
7663 if (object1.setSchedGroup != object2.setSchedGroup) {
7664 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7665 }
7666 if (object1.keeping != object2.keeping) {
7667 return object1.keeping ? -1 : 1;
7668 }
7669 if (object1.pid != object2.pid) {
7670 return object1.pid > object2.pid ? -1 : 1;
7671 }
7672 return 0;
7673 }
7674 };
7675
7676 Collections.sort(procs, comparator);
7677
7678 if (needSep) pw.println(" ");
7679 needSep = true;
7680 pw.println(" Process OOM control:");
7681 dumpProcessOomList(pw, this, procs, " ",
7682 "Proc", "PERS", true);
7683 needSep = true;
7684 }
7685
7686 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7687
7688 pw.println(" ");
7689 pw.println(" mHomeProcess: " + mHomeProcess);
7690 if (mHeavyWeightProcess != null) {
7691 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7692 }
7693
7694 return true;
7695 }
7696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697 /**
7698 * There are three ways to call this:
7699 * - no service specified: dump all the services
7700 * - a flattened component name that matched an existing service was specified as the
7701 * first arg: dump that one service
7702 * - the first arg isn't the flattened component name of an existing service:
7703 * dump all services whose component contains the first arg as a substring
7704 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007705 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007706 String[] newArgs;
7707 String componentNameString;
7708 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007709 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007710 componentNameString = null;
7711 newArgs = EMPTY_STRING_ARRAY;
7712 r = null;
7713 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007714 componentNameString = args[opti];
7715 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007716 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007717 synchronized (this) {
7718 r = componentName != null ? mServices.get(componentName) : null;
7719 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007720 newArgs = new String[args.length - opti];
7721 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007722 }
7723
7724 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007725 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007726 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007727 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7728 synchronized (this) {
7729 for (ServiceRecord r1 : mServices.values()) {
7730 if (componentNameString == null
7731 || r1.name.flattenToString().contains(componentNameString)) {
7732 services.add(r1);
7733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007734 }
7735 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007736 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007737 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007738 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007739 }
7740 }
7741
7742 /**
7743 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7744 * there is a thread associated with the service.
7745 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007746 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7747 pw.println("------------------------------------------------------------"
7748 + "-------------------");
7749 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007750 if (r.app != null && r.app.thread != null) {
7751 try {
7752 // flush anything that is already in the PrintWriter since the thread is going
7753 // to write to the file descriptor directly
7754 pw.flush();
7755 r.app.thread.dumpService(fd, r, args);
7756 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007757 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007758 } catch (RemoteException e) {
7759 pw.println("got a RemoteException while dumping the service");
7760 }
7761 }
7762 }
7763
Dianne Hackborn625ac272010-09-17 18:29:22 -07007764 /**
7765 * There are three things that cmd can be:
7766 * - a flattened component name that matched an existing activity
7767 * - the cmd arg isn't the flattened component name of an existing activity:
7768 * dump all activity whose component contains the cmd as a substring
7769 * - A hex number of the ActivityRecord object instance.
7770 */
7771 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7772 int opti, boolean dumpAll) {
7773 String[] newArgs;
7774 ComponentName componentName = ComponentName.unflattenFromString(name);
7775 int objectId = 0;
7776 try {
7777 objectId = Integer.parseInt(name, 16);
7778 name = null;
7779 componentName = null;
7780 } catch (RuntimeException e) {
7781 }
7782 newArgs = new String[args.length - opti];
7783 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7784
7785 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7786 synchronized (this) {
7787 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7788 if (componentName != null) {
7789 if (r1.intent.getComponent().equals(componentName)) {
7790 activities.add(r1);
7791 }
7792 } else if (name != null) {
7793 if (r1.intent.getComponent().flattenToString().contains(name)) {
7794 activities.add(r1);
7795 }
7796 } else if (System.identityHashCode(this) == objectId) {
7797 activities.add(r1);
7798 }
7799 }
7800 }
7801
7802 if (activities.size() <= 0) {
7803 return false;
7804 }
7805
7806 for (int i=0; i<activities.size(); i++) {
7807 dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
7808 }
7809 return true;
7810 }
7811
7812 /**
7813 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7814 * there is a thread associated with the activity.
7815 */
7816 private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
7817 boolean dumpAll) {
7818 pw.println(" Activity " + r.intent.getComponent().flattenToString());
7819 if (dumpAll) {
7820 synchronized (this) {
7821 pw.print(" * "); pw.println(r);
7822 r.dump(pw, " ");
7823 }
7824 pw.println("");
7825 }
7826 if (r.app != null && r.app.thread != null) {
7827 try {
7828 // flush anything that is already in the PrintWriter since the thread is going
7829 // to write to the file descriptor directly
7830 pw.flush();
7831 r.app.thread.dumpActivity(fd, r, args);
7832 pw.print("\n");
7833 pw.flush();
7834 } catch (RemoteException e) {
7835 pw.println("got a RemoteException while dumping the activity");
7836 }
7837 }
7838 }
7839
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007840 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7841 int opti, boolean dumpAll) {
7842 boolean needSep = false;
7843
7844 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007845 if (mRegisteredReceivers.size() > 0) {
7846 pw.println(" ");
7847 pw.println(" Registered Receivers:");
7848 Iterator it = mRegisteredReceivers.values().iterator();
7849 while (it.hasNext()) {
7850 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007851 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007852 r.dump(pw, " ");
7853 }
7854 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007856 pw.println(" ");
7857 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007858 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007859 needSep = true;
7860 }
7861
7862 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7863 || mPendingBroadcast != null) {
7864 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007865 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007866 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007867 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007868 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7869 pw.println(" Broadcast #" + i + ":");
7870 mParallelBroadcasts.get(i).dump(pw, " ");
7871 }
7872 if (mOrderedBroadcasts.size() > 0) {
7873 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007874 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007875 }
7876 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7877 pw.println(" Serialized Broadcast #" + i + ":");
7878 mOrderedBroadcasts.get(i).dump(pw, " ");
7879 }
7880 pw.println(" ");
7881 pw.println(" Pending broadcast:");
7882 if (mPendingBroadcast != null) {
7883 mPendingBroadcast.dump(pw, " ");
7884 } else {
7885 pw.println(" (null)");
7886 }
7887 needSep = true;
7888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007889
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007890 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007891 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007892 pw.println(" Historical broadcasts:");
7893 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7894 BroadcastRecord r = mBroadcastHistory[i];
7895 if (r == null) {
7896 break;
7897 }
7898 pw.println(" Historical Broadcast #" + i + ":");
7899 r.dump(pw, " ");
7900 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007901 needSep = true;
7902 }
7903
7904 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007905 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007906 pw.println(" Sticky broadcasts:");
7907 StringBuilder sb = new StringBuilder(128);
7908 for (Map.Entry<String, ArrayList<Intent>> ent
7909 : mStickyBroadcasts.entrySet()) {
7910 pw.print(" * Sticky action "); pw.print(ent.getKey());
7911 pw.println(":");
7912 ArrayList<Intent> intents = ent.getValue();
7913 final int N = intents.size();
7914 for (int i=0; i<N; i++) {
7915 sb.setLength(0);
7916 sb.append(" Intent: ");
7917 intents.get(i).toShortString(sb, true, false);
7918 pw.println(sb.toString());
7919 Bundle bundle = intents.get(i).getExtras();
7920 if (bundle != null) {
7921 pw.print(" ");
7922 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923 }
7924 }
7925 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007926 needSep = true;
7927 }
7928
7929 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007930 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007931 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007932 pw.println(" mHandler:");
7933 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007934 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007936
7937 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007938 }
7939
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007940 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7941 int opti, boolean dumpAll) {
7942 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007943
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007944 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945 if (mServices.size() > 0) {
7946 pw.println(" Active services:");
7947 Iterator<ServiceRecord> it = mServices.values().iterator();
7948 while (it.hasNext()) {
7949 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007950 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007951 r.dump(pw, " ");
7952 }
7953 needSep = true;
7954 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007956
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007957 if (mPendingServices.size() > 0) {
7958 if (needSep) pw.println(" ");
7959 pw.println(" Pending services:");
7960 for (int i=0; i<mPendingServices.size(); i++) {
7961 ServiceRecord r = mPendingServices.get(i);
7962 pw.print(" * Pending "); pw.println(r);
7963 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007964 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007965 needSep = true;
7966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007968 if (mRestartingServices.size() > 0) {
7969 if (needSep) pw.println(" ");
7970 pw.println(" Restarting services:");
7971 for (int i=0; i<mRestartingServices.size(); i++) {
7972 ServiceRecord r = mRestartingServices.get(i);
7973 pw.print(" * Restarting "); pw.println(r);
7974 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007975 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007976 needSep = true;
7977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007978
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007979 if (mStoppingServices.size() > 0) {
7980 if (needSep) pw.println(" ");
7981 pw.println(" Stopping services:");
7982 for (int i=0; i<mStoppingServices.size(); i++) {
7983 ServiceRecord r = mStoppingServices.get(i);
7984 pw.print(" * Stopping "); pw.println(r);
7985 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007986 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007987 needSep = true;
7988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007989
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007990 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007991 if (mServiceConnections.size() > 0) {
7992 if (needSep) pw.println(" ");
7993 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007994 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007995 = mServiceConnections.values().iterator();
7996 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007997 ArrayList<ConnectionRecord> r = it.next();
7998 for (int i=0; i<r.size(); i++) {
7999 pw.print(" * "); pw.println(r.get(i));
8000 r.get(i).dump(pw, " ");
8001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008002 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008003 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008004 }
8005 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008006
8007 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008008 }
8009
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008010 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8011 int opti, boolean dumpAll) {
8012 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008013
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008014 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008015 if (mProvidersByClass.size() > 0) {
8016 if (needSep) pw.println(" ");
8017 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008018 Iterator<Map.Entry<String, ContentProviderRecord>> it
8019 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008020 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008021 Map.Entry<String, ContentProviderRecord> e = it.next();
8022 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008023 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 r.dump(pw, " ");
8025 }
8026 needSep = true;
8027 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008028
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008029 if (mProvidersByName.size() > 0) {
8030 pw.println(" ");
8031 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008032 Iterator<Map.Entry<String, ContentProviderRecord>> it
8033 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008034 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008035 Map.Entry<String, ContentProviderRecord> e = it.next();
8036 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008037 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8038 pw.println(r);
8039 }
8040 needSep = true;
8041 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008042 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008043
8044 if (mLaunchingProviders.size() > 0) {
8045 if (needSep) pw.println(" ");
8046 pw.println(" Launching content providers:");
8047 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8048 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8049 pw.println(mLaunchingProviders.get(i));
8050 }
8051 needSep = true;
8052 }
8053
8054 if (mGrantedUriPermissions.size() > 0) {
8055 pw.println();
8056 pw.println("Granted Uri Permissions:");
8057 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8058 int uid = mGrantedUriPermissions.keyAt(i);
8059 HashMap<Uri, UriPermission> perms
8060 = mGrantedUriPermissions.valueAt(i);
8061 pw.print(" * UID "); pw.print(uid);
8062 pw.println(" holds:");
8063 for (UriPermission perm : perms.values()) {
8064 pw.print(" "); pw.println(perm);
8065 perm.dump(pw, " ");
8066 }
8067 }
8068 needSep = true;
8069 }
8070
8071 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 }
8073
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008074 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8075 int opti, boolean dumpAll) {
8076 boolean needSep = false;
8077
8078 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008079 if (this.mIntentSenderRecords.size() > 0) {
8080 Iterator<WeakReference<PendingIntentRecord>> it
8081 = mIntentSenderRecords.values().iterator();
8082 while (it.hasNext()) {
8083 WeakReference<PendingIntentRecord> ref = it.next();
8084 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008085 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008086 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008087 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008088 rec.dump(pw, " ");
8089 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008090 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008091 }
8092 }
8093 }
8094 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008095
8096 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008097 }
8098
8099 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008100 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008101 TaskRecord lastTask = null;
8102 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008103 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008104 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008105 if (lastTask != r.task) {
8106 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008107 pw.print(prefix);
8108 pw.print(full ? "* " : " ");
8109 pw.println(lastTask);
8110 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008111 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008113 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008114 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8115 pw.print(" #"); pw.print(i); pw.print(": ");
8116 pw.println(r);
8117 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008118 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008120 }
8121 }
8122
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008123 private static String buildOomTag(String prefix, String space, int val, int base) {
8124 if (val == base) {
8125 if (space == null) return prefix;
8126 return prefix + " ";
8127 }
8128 return prefix + "+" + Integer.toString(val-base);
8129 }
8130
8131 private static final int dumpProcessList(PrintWriter pw,
8132 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008133 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008134 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008135 final int N = list.size()-1;
8136 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008138 pw.println(String.format("%s%s #%2d: %s",
8139 prefix, (r.persistent ? persistentLabel : normalLabel),
8140 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008141 if (r.persistent) {
8142 numPers++;
8143 }
8144 }
8145 return numPers;
8146 }
8147
Dianne Hackborn287952c2010-09-22 22:34:31 -07008148 private static final void dumpProcessOomList(PrintWriter pw,
8149 ActivityManagerService service, List<ProcessRecord> list,
8150 String prefix, String normalLabel, String persistentLabel,
8151 boolean inclDetails) {
8152
8153 final long curRealtime = SystemClock.elapsedRealtime();
8154 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8155 final long curUptime = SystemClock.uptimeMillis();
8156 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8157
8158 final int N = list.size()-1;
8159 for (int i=N; i>=0; i--) {
8160 ProcessRecord r = list.get(i);
8161 String oomAdj;
8162 if (r.setAdj >= EMPTY_APP_ADJ) {
8163 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8164 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8165 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8166 } else if (r.setAdj >= HOME_APP_ADJ) {
8167 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8168 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8169 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8170 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8171 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8172 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8173 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8174 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8175 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8176 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8177 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8178 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8179 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8180 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8181 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8182 } else if (r.setAdj >= SYSTEM_ADJ) {
8183 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8184 } else {
8185 oomAdj = Integer.toString(r.setAdj);
8186 }
8187 String schedGroup;
8188 switch (r.setSchedGroup) {
8189 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8190 schedGroup = "B";
8191 break;
8192 case Process.THREAD_GROUP_DEFAULT:
8193 schedGroup = "F";
8194 break;
8195 default:
8196 schedGroup = Integer.toString(r.setSchedGroup);
8197 break;
8198 }
8199 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8200 prefix, (r.persistent ? persistentLabel : normalLabel),
8201 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8202 if (r.adjSource != null || r.adjTarget != null) {
8203 pw.print(prefix);
8204 pw.print(" ");
8205 if (r.adjTarget instanceof ComponentName) {
8206 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8207 } else if (r.adjTarget != null) {
8208 pw.print(r.adjTarget.toString());
8209 } else {
8210 pw.print("{null}");
8211 }
8212 pw.print("<=");
8213 if (r.adjSource instanceof ProcessRecord) {
8214 pw.print("Proc{");
8215 pw.print(((ProcessRecord)r.adjSource).toShortString());
8216 pw.println("}");
8217 } else if (r.adjSource != null) {
8218 pw.println(r.adjSource.toString());
8219 } else {
8220 pw.println("{null}");
8221 }
8222 }
8223 if (inclDetails) {
8224 pw.print(prefix);
8225 pw.print(" ");
8226 pw.print("oom: max="); pw.print(r.maxAdj);
8227 pw.print(" hidden="); pw.print(r.hiddenAdj);
8228 pw.print(" curRaw="); pw.print(r.curRawAdj);
8229 pw.print(" setRaw="); pw.print(r.setRawAdj);
8230 pw.print(" cur="); pw.print(r.curAdj);
8231 pw.print(" set="); pw.println(r.setAdj);
8232 pw.print(prefix);
8233 pw.print(" ");
8234 pw.print("keeping="); pw.print(r.keeping);
8235 pw.print(" hidden="); pw.print(r.hidden);
8236 pw.print(" empty="); pw.println(r.empty);
8237
8238 if (!r.keeping) {
8239 if (r.lastWakeTime != 0) {
8240 long wtime;
8241 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8242 synchronized (stats) {
8243 wtime = stats.getProcessWakeTime(r.info.uid,
8244 r.pid, curRealtime);
8245 }
8246 long timeUsed = wtime - r.lastWakeTime;
8247 pw.print(prefix);
8248 pw.print(" ");
8249 pw.print("keep awake over ");
8250 TimeUtils.formatDuration(realtimeSince, pw);
8251 pw.print(" used ");
8252 TimeUtils.formatDuration(timeUsed, pw);
8253 pw.print(" (");
8254 pw.print((timeUsed*100)/realtimeSince);
8255 pw.println("%)");
8256 }
8257 if (r.lastCpuTime != 0) {
8258 long timeUsed = r.curCpuTime - r.lastCpuTime;
8259 pw.print(prefix);
8260 pw.print(" ");
8261 pw.print("run cpu over ");
8262 TimeUtils.formatDuration(uptimeSince, pw);
8263 pw.print(" used ");
8264 TimeUtils.formatDuration(timeUsed, pw);
8265 pw.print(" (");
8266 pw.print((timeUsed*100)/uptimeSince);
8267 pw.println("%)");
8268 }
8269 }
8270 }
8271 }
8272 }
8273
Dianne Hackborn472ad872010-04-07 17:31:48 -07008274 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008275 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008276 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008277 long uptime = SystemClock.uptimeMillis();
8278 long realtime = SystemClock.elapsedRealtime();
8279
8280 if (isCheckinRequest) {
8281 // short checkin version
8282 pw.println(uptime + "," + realtime);
8283 pw.flush();
8284 } else {
8285 pw.println("Applications Memory Usage (kB):");
8286 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8287 }
8288 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8289 ProcessRecord r = (ProcessRecord)list.get(i);
8290 if (r.thread != null) {
8291 if (!isCheckinRequest) {
8292 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8293 pw.flush();
8294 }
8295 try {
8296 r.thread.asBinder().dump(fd, args);
8297 } catch (RemoteException e) {
8298 if (!isCheckinRequest) {
8299 pw.println("Got RemoteException!");
8300 pw.flush();
8301 }
8302 }
8303 }
8304 }
8305 }
8306
8307 /**
8308 * Searches array of arguments for the specified string
8309 * @param args array of argument strings
8310 * @param value value to search for
8311 * @return true if the value is contained in the array
8312 */
8313 private static boolean scanArgs(String[] args, String value) {
8314 if (args != null) {
8315 for (String arg : args) {
8316 if (value.equals(arg)) {
8317 return true;
8318 }
8319 }
8320 }
8321 return false;
8322 }
8323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008324 private final void killServicesLocked(ProcessRecord app,
8325 boolean allowRestart) {
8326 // Report disconnected services.
8327 if (false) {
8328 // XXX we are letting the client link to the service for
8329 // death notifications.
8330 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008331 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008332 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008333 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008334 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008335 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008336 = r.connections.values().iterator();
8337 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008338 ArrayList<ConnectionRecord> cl = jt.next();
8339 for (int i=0; i<cl.size(); i++) {
8340 ConnectionRecord c = cl.get(i);
8341 if (c.binding.client != app) {
8342 try {
8343 //c.conn.connected(r.className, null);
8344 } catch (Exception e) {
8345 // todo: this should be asynchronous!
8346 Slog.w(TAG, "Exception thrown disconnected servce "
8347 + r.shortName
8348 + " from app " + app.processName, e);
8349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008350 }
8351 }
8352 }
8353 }
8354 }
8355 }
8356 }
8357
8358 // Clean up any connections this application has to other services.
8359 if (app.connections.size() > 0) {
8360 Iterator<ConnectionRecord> it = app.connections.iterator();
8361 while (it.hasNext()) {
8362 ConnectionRecord r = it.next();
8363 removeConnectionLocked(r, app, null);
8364 }
8365 }
8366 app.connections.clear();
8367
8368 if (app.services.size() != 0) {
8369 // Any services running in the application need to be placed
8370 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008371 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008372 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008373 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008374 synchronized (sr.stats.getBatteryStats()) {
8375 sr.stats.stopLaunchedLocked();
8376 }
8377 sr.app = null;
8378 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008379 if (mStoppingServices.remove(sr)) {
8380 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8381 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008382
8383 boolean hasClients = sr.bindings.size() > 0;
8384 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 Iterator<IntentBindRecord> bindings
8386 = sr.bindings.values().iterator();
8387 while (bindings.hasNext()) {
8388 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008389 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008390 + ": shouldUnbind=" + b.hasBound);
8391 b.binder = null;
8392 b.requested = b.received = b.hasBound = false;
8393 }
8394 }
8395
8396 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008397 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008398 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008399 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008400 sr.crashCount, sr.shortName, app.pid);
8401 bringDownServiceLocked(sr, true);
8402 } else if (!allowRestart) {
8403 bringDownServiceLocked(sr, true);
8404 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008405 boolean canceled = scheduleServiceRestartLocked(sr, true);
8406
8407 // Should the service remain running? Note that in the
8408 // extreme case of so many attempts to deliver a command
8409 // that it failed, that we also will stop it here.
8410 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8411 if (sr.pendingStarts.size() == 0) {
8412 sr.startRequested = false;
8413 if (!hasClients) {
8414 // Whoops, no reason to restart!
8415 bringDownServiceLocked(sr, true);
8416 }
8417 }
8418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008419 }
8420 }
8421
8422 if (!allowRestart) {
8423 app.services.clear();
8424 }
8425 }
8426
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008427 // Make sure we have no more records on the stopping list.
8428 int i = mStoppingServices.size();
8429 while (i > 0) {
8430 i--;
8431 ServiceRecord sr = mStoppingServices.get(i);
8432 if (sr.app == app) {
8433 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008434 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008435 }
8436 }
8437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008438 app.executingServices.clear();
8439 }
8440
8441 private final void removeDyingProviderLocked(ProcessRecord proc,
8442 ContentProviderRecord cpr) {
8443 synchronized (cpr) {
8444 cpr.launchingApp = null;
8445 cpr.notifyAll();
8446 }
8447
8448 mProvidersByClass.remove(cpr.info.name);
8449 String names[] = cpr.info.authority.split(";");
8450 for (int j = 0; j < names.length; j++) {
8451 mProvidersByName.remove(names[j]);
8452 }
8453
8454 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8455 while (cit.hasNext()) {
8456 ProcessRecord capp = cit.next();
8457 if (!capp.persistent && capp.thread != null
8458 && capp.pid != 0
8459 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008460 Slog.i(TAG, "Kill " + capp.processName
8461 + " (pid " + capp.pid + "): provider " + cpr.info.name
8462 + " in dying process " + proc.processName);
8463 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8464 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008465 Process.killProcess(capp.pid);
8466 }
8467 }
8468
8469 mLaunchingProviders.remove(cpr);
8470 }
8471
8472 /**
8473 * Main code for cleaning up a process when it has gone away. This is
8474 * called both as a result of the process dying, or directly when stopping
8475 * a process when running in single process mode.
8476 */
8477 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8478 boolean restarting, int index) {
8479 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008480 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008481 }
8482
Dianne Hackborn36124872009-10-08 16:22:03 -07008483 mProcessesToGc.remove(app);
8484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008485 // Dismiss any open dialogs.
8486 if (app.crashDialog != null) {
8487 app.crashDialog.dismiss();
8488 app.crashDialog = null;
8489 }
8490 if (app.anrDialog != null) {
8491 app.anrDialog.dismiss();
8492 app.anrDialog = null;
8493 }
8494 if (app.waitDialog != null) {
8495 app.waitDialog.dismiss();
8496 app.waitDialog = null;
8497 }
8498
8499 app.crashing = false;
8500 app.notResponding = false;
8501
8502 app.resetPackageList();
8503 app.thread = null;
8504 app.forcingToForeground = null;
8505 app.foregroundServices = false;
8506
8507 killServicesLocked(app, true);
8508
8509 boolean restart = false;
8510
8511 int NL = mLaunchingProviders.size();
8512
8513 // Remove published content providers.
8514 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008515 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008516 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008517 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518 cpr.provider = null;
8519 cpr.app = null;
8520
8521 // See if someone is waiting for this provider... in which
8522 // case we don't remove it, but just let it restart.
8523 int i = 0;
8524 if (!app.bad) {
8525 for (; i<NL; i++) {
8526 if (mLaunchingProviders.get(i) == cpr) {
8527 restart = true;
8528 break;
8529 }
8530 }
8531 } else {
8532 i = NL;
8533 }
8534
8535 if (i >= NL) {
8536 removeDyingProviderLocked(app, cpr);
8537 NL = mLaunchingProviders.size();
8538 }
8539 }
8540 app.pubProviders.clear();
8541 }
8542
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008543 // Take care of any launching providers waiting for this process.
8544 if (checkAppInLaunchingProvidersLocked(app, false)) {
8545 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008546 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008548 // Unregister from connected content providers.
8549 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008550 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008551 while (it.hasNext()) {
8552 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8553 cpr.clients.remove(app);
8554 }
8555 app.conProviders.clear();
8556 }
8557
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008558 // At this point there may be remaining entries in mLaunchingProviders
8559 // where we were the only one waiting, so they are no longer of use.
8560 // Look for these and clean up if found.
8561 // XXX Commented out for now. Trying to figure out a way to reproduce
8562 // the actual situation to identify what is actually going on.
8563 if (false) {
8564 for (int i=0; i<NL; i++) {
8565 ContentProviderRecord cpr = (ContentProviderRecord)
8566 mLaunchingProviders.get(i);
8567 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8568 synchronized (cpr) {
8569 cpr.launchingApp = null;
8570 cpr.notifyAll();
8571 }
8572 }
8573 }
8574 }
8575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008576 skipCurrentReceiverLocked(app);
8577
8578 // Unregister any receivers.
8579 if (app.receivers.size() > 0) {
8580 Iterator<ReceiverList> it = app.receivers.iterator();
8581 while (it.hasNext()) {
8582 removeReceiverLocked(it.next());
8583 }
8584 app.receivers.clear();
8585 }
8586
Christopher Tate181fafa2009-05-14 11:12:14 -07008587 // If the app is undergoing backup, tell the backup manager about it
8588 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008589 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008590 try {
8591 IBackupManager bm = IBackupManager.Stub.asInterface(
8592 ServiceManager.getService(Context.BACKUP_SERVICE));
8593 bm.agentDisconnected(app.info.packageName);
8594 } catch (RemoteException e) {
8595 // can't happen; backup manager is local
8596 }
8597 }
8598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008599 // If the caller is restarting this app, then leave it in its
8600 // current lists and let the caller take care of it.
8601 if (restarting) {
8602 return;
8603 }
8604
8605 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008606 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008607 "Removing non-persistent process during cleanup: " + app);
8608 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008609 if (mHeavyWeightProcess == app) {
8610 mHeavyWeightProcess = null;
8611 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008613 } else if (!app.removed) {
8614 // This app is persistent, so we need to keep its record around.
8615 // If it is not already on the pending app list, add it there
8616 // and start a new process for it.
8617 app.thread = null;
8618 app.forcingToForeground = null;
8619 app.foregroundServices = false;
8620 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8621 mPersistentStartingProcesses.add(app);
8622 restart = true;
8623 }
8624 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008625 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8626 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008627 mProcessesOnHold.remove(app);
8628
The Android Open Source Project4df24232009-03-05 14:34:35 -08008629 if (app == mHomeProcess) {
8630 mHomeProcess = null;
8631 }
8632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 if (restart) {
8634 // We have components that still need to be running in the
8635 // process, so re-launch it.
8636 mProcessNames.put(app.processName, app.info.uid, app);
8637 startProcessLocked(app, "restart", app.processName);
8638 } else if (app.pid > 0 && app.pid != MY_PID) {
8639 // Goodbye!
8640 synchronized (mPidsSelfLocked) {
8641 mPidsSelfLocked.remove(app.pid);
8642 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8643 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008644 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008645 }
8646 }
8647
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008648 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8649 // Look through the content providers we are waiting to have launched,
8650 // and if any run in this process then either schedule a restart of
8651 // the process or kill the client waiting for it if this process has
8652 // gone bad.
8653 int NL = mLaunchingProviders.size();
8654 boolean restart = false;
8655 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008656 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008657 if (cpr.launchingApp == app) {
8658 if (!alwaysBad && !app.bad) {
8659 restart = true;
8660 } else {
8661 removeDyingProviderLocked(app, cpr);
8662 NL = mLaunchingProviders.size();
8663 }
8664 }
8665 }
8666 return restart;
8667 }
8668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 // =========================================================
8670 // SERVICES
8671 // =========================================================
8672
8673 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8674 ActivityManager.RunningServiceInfo info =
8675 new ActivityManager.RunningServiceInfo();
8676 info.service = r.name;
8677 if (r.app != null) {
8678 info.pid = r.app.pid;
8679 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008680 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008681 info.process = r.processName;
8682 info.foreground = r.isForeground;
8683 info.activeSince = r.createTime;
8684 info.started = r.startRequested;
8685 info.clientCount = r.connections.size();
8686 info.crashCount = r.crashCount;
8687 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008688 if (r.isForeground) {
8689 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8690 }
8691 if (r.startRequested) {
8692 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8693 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008694 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008695 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8696 }
8697 if (r.app != null && r.app.persistent) {
8698 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8699 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008700
8701 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8702 for (int i=0; i<connl.size(); i++) {
8703 ConnectionRecord conn = connl.get(i);
8704 if (conn.clientLabel != 0) {
8705 info.clientPackage = conn.binding.client.info.packageName;
8706 info.clientLabel = conn.clientLabel;
8707 return info;
8708 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008709 }
8710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008711 return info;
8712 }
8713
8714 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8715 int flags) {
8716 synchronized (this) {
8717 ArrayList<ActivityManager.RunningServiceInfo> res
8718 = new ArrayList<ActivityManager.RunningServiceInfo>();
8719
8720 if (mServices.size() > 0) {
8721 Iterator<ServiceRecord> it = mServices.values().iterator();
8722 while (it.hasNext() && res.size() < maxNum) {
8723 res.add(makeRunningServiceInfoLocked(it.next()));
8724 }
8725 }
8726
8727 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8728 ServiceRecord r = mRestartingServices.get(i);
8729 ActivityManager.RunningServiceInfo info =
8730 makeRunningServiceInfoLocked(r);
8731 info.restarting = r.nextRestartTime;
8732 res.add(info);
8733 }
8734
8735 return res;
8736 }
8737 }
8738
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008739 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8740 synchronized (this) {
8741 ServiceRecord r = mServices.get(name);
8742 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008743 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8744 for (int i=0; i<conn.size(); i++) {
8745 if (conn.get(i).clientIntent != null) {
8746 return conn.get(i).clientIntent;
8747 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008748 }
8749 }
8750 }
8751 }
8752 return null;
8753 }
8754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008755 private final ServiceRecord findServiceLocked(ComponentName name,
8756 IBinder token) {
8757 ServiceRecord r = mServices.get(name);
8758 return r == token ? r : null;
8759 }
8760
8761 private final class ServiceLookupResult {
8762 final ServiceRecord record;
8763 final String permission;
8764
8765 ServiceLookupResult(ServiceRecord _record, String _permission) {
8766 record = _record;
8767 permission = _permission;
8768 }
8769 };
8770
8771 private ServiceLookupResult findServiceLocked(Intent service,
8772 String resolvedType) {
8773 ServiceRecord r = null;
8774 if (service.getComponent() != null) {
8775 r = mServices.get(service.getComponent());
8776 }
8777 if (r == null) {
8778 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8779 r = mServicesByIntent.get(filter);
8780 }
8781
8782 if (r == null) {
8783 try {
8784 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008785 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008786 service, resolvedType, 0);
8787 ServiceInfo sInfo =
8788 rInfo != null ? rInfo.serviceInfo : null;
8789 if (sInfo == null) {
8790 return null;
8791 }
8792
8793 ComponentName name = new ComponentName(
8794 sInfo.applicationInfo.packageName, sInfo.name);
8795 r = mServices.get(name);
8796 } catch (RemoteException ex) {
8797 // pm is in same process, this will never happen.
8798 }
8799 }
8800 if (r != null) {
8801 int callingPid = Binder.getCallingPid();
8802 int callingUid = Binder.getCallingUid();
8803 if (checkComponentPermission(r.permission,
8804 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8805 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008806 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807 + " from pid=" + callingPid
8808 + ", uid=" + callingUid
8809 + " requires " + r.permission);
8810 return new ServiceLookupResult(null, r.permission);
8811 }
8812 return new ServiceLookupResult(r, null);
8813 }
8814 return null;
8815 }
8816
8817 private class ServiceRestarter implements Runnable {
8818 private ServiceRecord mService;
8819
8820 void setService(ServiceRecord service) {
8821 mService = service;
8822 }
8823
8824 public void run() {
8825 synchronized(ActivityManagerService.this) {
8826 performServiceRestartLocked(mService);
8827 }
8828 }
8829 }
8830
8831 private ServiceLookupResult retrieveServiceLocked(Intent service,
8832 String resolvedType, int callingPid, int callingUid) {
8833 ServiceRecord r = null;
8834 if (service.getComponent() != null) {
8835 r = mServices.get(service.getComponent());
8836 }
8837 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8838 r = mServicesByIntent.get(filter);
8839 if (r == null) {
8840 try {
8841 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008842 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008843 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008844 ServiceInfo sInfo =
8845 rInfo != null ? rInfo.serviceInfo : null;
8846 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008847 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008848 ": not found");
8849 return null;
8850 }
8851
8852 ComponentName name = new ComponentName(
8853 sInfo.applicationInfo.packageName, sInfo.name);
8854 r = mServices.get(name);
8855 if (r == null) {
8856 filter = new Intent.FilterComparison(service.cloneFilter());
8857 ServiceRestarter res = new ServiceRestarter();
8858 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8859 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8860 synchronized (stats) {
8861 ss = stats.getServiceStatsLocked(
8862 sInfo.applicationInfo.uid, sInfo.packageName,
8863 sInfo.name);
8864 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008865 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008866 res.setService(r);
8867 mServices.put(name, r);
8868 mServicesByIntent.put(filter, r);
8869
8870 // Make sure this component isn't in the pending list.
8871 int N = mPendingServices.size();
8872 for (int i=0; i<N; i++) {
8873 ServiceRecord pr = mPendingServices.get(i);
8874 if (pr.name.equals(name)) {
8875 mPendingServices.remove(i);
8876 i--;
8877 N--;
8878 }
8879 }
8880 }
8881 } catch (RemoteException ex) {
8882 // pm is in same process, this will never happen.
8883 }
8884 }
8885 if (r != null) {
8886 if (checkComponentPermission(r.permission,
8887 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8888 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008889 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008890 + " from pid=" + Binder.getCallingPid()
8891 + ", uid=" + Binder.getCallingUid()
8892 + " requires " + r.permission);
8893 return new ServiceLookupResult(null, r.permission);
8894 }
8895 return new ServiceLookupResult(r, null);
8896 }
8897 return null;
8898 }
8899
Dianne Hackborn287952c2010-09-22 22:34:31 -07008900 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8901 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8902 + why + " of " + r + " in app " + r.app);
8903 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8904 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008905 long now = SystemClock.uptimeMillis();
8906 if (r.executeNesting == 0 && r.app != null) {
8907 if (r.app.executingServices.size() == 0) {
8908 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8909 msg.obj = r.app;
8910 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8911 }
8912 r.app.executingServices.add(r);
8913 }
8914 r.executeNesting++;
8915 r.executingStart = now;
8916 }
8917
8918 private final void sendServiceArgsLocked(ServiceRecord r,
8919 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008920 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008921 if (N == 0) {
8922 return;
8923 }
8924
Dianne Hackborn39792d22010-08-19 18:01:52 -07008925 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008926 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008927 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008928 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8929 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008930 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008931 // If somehow we got a dummy start at the front, then
8932 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008933 continue;
8934 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008935 si.deliveredTime = SystemClock.uptimeMillis();
8936 r.deliveredStarts.add(si);
8937 si.deliveryCount++;
8938 if (si.targetPermissionUid >= 0) {
8939 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008940 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008941 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008942 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008943 if (!oomAdjusted) {
8944 oomAdjusted = true;
8945 updateOomAdjLocked(r.app);
8946 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008947 int flags = 0;
8948 if (si.deliveryCount > 0) {
8949 flags |= Service.START_FLAG_RETRY;
8950 }
8951 if (si.doneExecutingCount > 0) {
8952 flags |= Service.START_FLAG_REDELIVERY;
8953 }
8954 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008955 } catch (RemoteException e) {
8956 // Remote process gone... we'll let the normal cleanup take
8957 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008958 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008959 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008960 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008961 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 break;
8963 }
8964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008965 }
8966
8967 private final boolean requestServiceBindingLocked(ServiceRecord r,
8968 IntentBindRecord i, boolean rebind) {
8969 if (r.app == null || r.app.thread == null) {
8970 // If service is not currently running, can't yet bind.
8971 return false;
8972 }
8973 if ((!i.requested || rebind) && i.apps.size() > 0) {
8974 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008975 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008976 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8977 if (!rebind) {
8978 i.requested = true;
8979 }
8980 i.hasBound = true;
8981 i.doRebind = false;
8982 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008983 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984 return false;
8985 }
8986 }
8987 return true;
8988 }
8989
8990 private final void requestServiceBindingsLocked(ServiceRecord r) {
8991 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8992 while (bindings.hasNext()) {
8993 IntentBindRecord i = bindings.next();
8994 if (!requestServiceBindingLocked(r, i, false)) {
8995 break;
8996 }
8997 }
8998 }
8999
9000 private final void realStartServiceLocked(ServiceRecord r,
9001 ProcessRecord app) throws RemoteException {
9002 if (app.thread == null) {
9003 throw new RemoteException();
9004 }
9005
9006 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009007 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009008
9009 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009010 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009011 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009012
9013 boolean created = false;
9014 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009015 mStringBuilder.setLength(0);
9016 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009017 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009018 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009019 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009020 synchronized (r.stats.getBatteryStats()) {
9021 r.stats.startLaunchedLocked();
9022 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009023 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009024 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009025 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009026 created = true;
9027 } finally {
9028 if (!created) {
9029 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009030 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009031 }
9032 }
9033
9034 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009035
9036 // If the service is in the started state, and there are no
9037 // pending arguments, then fake up one so its onStartCommand() will
9038 // be called.
9039 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9040 r.lastStartId++;
9041 if (r.lastStartId < 1) {
9042 r.lastStartId = 1;
9043 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009044 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009045 }
9046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009047 sendServiceArgsLocked(r, true);
9048 }
9049
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009050 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9051 boolean allowCancel) {
9052 boolean canceled = false;
9053
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009054 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009055 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009056 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009057
9058 // Any delivered but not yet finished starts should be put back
9059 // on the pending list.
9060 final int N = r.deliveredStarts.size();
9061 if (N > 0) {
9062 for (int i=N-1; i>=0; i--) {
9063 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009064 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009065 if (si.intent == null) {
9066 // We'll generate this again if needed.
9067 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9068 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9069 r.pendingStarts.add(0, si);
9070 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9071 dur *= 2;
9072 if (minDuration < dur) minDuration = dur;
9073 if (resetTime < dur) resetTime = dur;
9074 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009075 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009076 + r.name);
9077 canceled = true;
9078 }
9079 }
9080 r.deliveredStarts.clear();
9081 }
9082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009083 r.totalRestartCount++;
9084 if (r.restartDelay == 0) {
9085 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009086 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009087 } else {
9088 // If it has been a "reasonably long time" since the service
9089 // was started, then reset our restart duration back to
9090 // the beginning, so we don't infinitely increase the duration
9091 // on a service that just occasionally gets killed (which is
9092 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009093 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009094 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009095 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009096 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009097 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009098 if (r.restartDelay < minDuration) {
9099 r.restartDelay = minDuration;
9100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009101 }
9102 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009103
9104 r.nextRestartTime = now + r.restartDelay;
9105
9106 // Make sure that we don't end up restarting a bunch of services
9107 // all at the same time.
9108 boolean repeat;
9109 do {
9110 repeat = false;
9111 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9112 ServiceRecord r2 = mRestartingServices.get(i);
9113 if (r2 != r && r.nextRestartTime
9114 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9115 && r.nextRestartTime
9116 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9117 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9118 r.restartDelay = r.nextRestartTime - now;
9119 repeat = true;
9120 break;
9121 }
9122 }
9123 } while (repeat);
9124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 if (!mRestartingServices.contains(r)) {
9126 mRestartingServices.add(r);
9127 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009128
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009129 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009131 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009132 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009133 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009134 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009135 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009136 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009137 r.shortName, r.restartDelay);
9138
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009139 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009140 }
9141
9142 final void performServiceRestartLocked(ServiceRecord r) {
9143 if (!mRestartingServices.contains(r)) {
9144 return;
9145 }
9146 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9147 }
9148
9149 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9150 if (r.restartDelay == 0) {
9151 return false;
9152 }
9153 r.resetRestartCounter();
9154 mRestartingServices.remove(r);
9155 mHandler.removeCallbacks(r.restarter);
9156 return true;
9157 }
9158
9159 private final boolean bringUpServiceLocked(ServiceRecord r,
9160 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009161 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009162 //r.dump(" ");
9163
Dianne Hackborn36124872009-10-08 16:22:03 -07009164 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009165 sendServiceArgsLocked(r, false);
9166 return true;
9167 }
9168
9169 if (!whileRestarting && r.restartDelay > 0) {
9170 // If waiting for a restart, then do nothing.
9171 return true;
9172 }
9173
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009174 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009175
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009176 // We are now bringing the service up, so no longer in the
9177 // restarting state.
9178 mRestartingServices.remove(r);
9179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009180 final String appName = r.processName;
9181 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9182 if (app != null && app.thread != null) {
9183 try {
9184 realStartServiceLocked(r, app);
9185 return true;
9186 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009187 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009188 }
9189
9190 // If a dead object exception was thrown -- fall through to
9191 // restart the application.
9192 }
9193
Dianne Hackborn36124872009-10-08 16:22:03 -07009194 // Not running -- get it started, and enqueue this service record
9195 // to be executed when the app comes up.
9196 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9197 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009198 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009199 + r.appInfo.packageName + "/"
9200 + r.appInfo.uid + " for service "
9201 + r.intent.getIntent() + ": process is bad");
9202 bringDownServiceLocked(r, true);
9203 return false;
9204 }
9205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009206 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009207 mPendingServices.add(r);
9208 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009210 return true;
9211 }
9212
9213 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009214 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009215 //r.dump(" ");
9216
9217 // Does it still need to run?
9218 if (!force && r.startRequested) {
9219 return;
9220 }
9221 if (r.connections.size() > 0) {
9222 if (!force) {
9223 // XXX should probably keep a count of the number of auto-create
9224 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009225 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009227 ArrayList<ConnectionRecord> cr = it.next();
9228 for (int i=0; i<cr.size(); i++) {
9229 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9230 return;
9231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009232 }
9233 }
9234 }
9235
9236 // Report to all of the connections that the service is no longer
9237 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009238 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009239 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009240 ArrayList<ConnectionRecord> c = it.next();
9241 for (int i=0; i<c.size(); i++) {
9242 try {
9243 c.get(i).conn.connected(r.name, null);
9244 } catch (Exception e) {
9245 Slog.w(TAG, "Failure disconnecting service " + r.name +
9246 " to connection " + c.get(i).conn.asBinder() +
9247 " (in " + c.get(i).binding.client.processName + ")", e);
9248 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009249 }
9250 }
9251 }
9252
9253 // Tell the service that it has been unbound.
9254 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9255 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9256 while (it.hasNext()) {
9257 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009258 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009259 + ": hasBound=" + ibr.hasBound);
9260 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9261 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009262 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009263 updateOomAdjLocked(r.app);
9264 ibr.hasBound = false;
9265 r.app.thread.scheduleUnbindService(r,
9266 ibr.intent.getIntent());
9267 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009268 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009269 + r.shortName, e);
9270 serviceDoneExecutingLocked(r, true);
9271 }
9272 }
9273 }
9274 }
9275
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009276 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009277 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009278 System.identityHashCode(r), r.shortName,
9279 (r.app != null) ? r.app.pid : -1);
9280
9281 mServices.remove(r.name);
9282 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009283 r.totalRestartCount = 0;
9284 unscheduleServiceRestartLocked(r);
9285
9286 // Also make sure it is not on the pending list.
9287 int N = mPendingServices.size();
9288 for (int i=0; i<N; i++) {
9289 if (mPendingServices.get(i) == r) {
9290 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009291 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009292 i--;
9293 N--;
9294 }
9295 }
9296
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009297 r.cancelNotification();
9298 r.isForeground = false;
9299 r.foregroundId = 0;
9300 r.foregroundNoti = null;
9301
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009302 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009303 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009304 r.pendingStarts.clear();
9305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009306 if (r.app != null) {
9307 synchronized (r.stats.getBatteryStats()) {
9308 r.stats.stopLaunchedLocked();
9309 }
9310 r.app.services.remove(r);
9311 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009313 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009314 mStoppingServices.add(r);
9315 updateOomAdjLocked(r.app);
9316 r.app.thread.scheduleStopService(r);
9317 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009318 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009319 + r.shortName, e);
9320 serviceDoneExecutingLocked(r, true);
9321 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009322 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009323 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009324 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009325 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009326 }
9327 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009328 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009329 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009330 }
9331 }
9332
9333 ComponentName startServiceLocked(IApplicationThread caller,
9334 Intent service, String resolvedType,
9335 int callingPid, int callingUid) {
9336 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009337 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009338 + " type=" + resolvedType + " args=" + service.getExtras());
9339
9340 if (caller != null) {
9341 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9342 if (callerApp == null) {
9343 throw new SecurityException(
9344 "Unable to find app for caller " + caller
9345 + " (pid=" + Binder.getCallingPid()
9346 + ") when starting service " + service);
9347 }
9348 }
9349
9350 ServiceLookupResult res =
9351 retrieveServiceLocked(service, resolvedType,
9352 callingPid, callingUid);
9353 if (res == null) {
9354 return null;
9355 }
9356 if (res.record == null) {
9357 return new ComponentName("!", res.permission != null
9358 ? res.permission : "private to package");
9359 }
9360 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009361 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9362 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009363 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009364 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009365 }
9366 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009367 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009368 r.lastStartId++;
9369 if (r.lastStartId < 1) {
9370 r.lastStartId = 1;
9371 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009372 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9373 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009374 r.lastActivity = SystemClock.uptimeMillis();
9375 synchronized (r.stats.getBatteryStats()) {
9376 r.stats.startRunningLocked();
9377 }
9378 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9379 return new ComponentName("!", "Service process is bad");
9380 }
9381 return r.name;
9382 }
9383 }
9384
9385 public ComponentName startService(IApplicationThread caller, Intent service,
9386 String resolvedType) {
9387 // Refuse possible leaked file descriptors
9388 if (service != null && service.hasFileDescriptors() == true) {
9389 throw new IllegalArgumentException("File descriptors passed in Intent");
9390 }
9391
9392 synchronized(this) {
9393 final int callingPid = Binder.getCallingPid();
9394 final int callingUid = Binder.getCallingUid();
9395 final long origId = Binder.clearCallingIdentity();
9396 ComponentName res = startServiceLocked(caller, service,
9397 resolvedType, callingPid, callingUid);
9398 Binder.restoreCallingIdentity(origId);
9399 return res;
9400 }
9401 }
9402
9403 ComponentName startServiceInPackage(int uid,
9404 Intent service, String resolvedType) {
9405 synchronized(this) {
9406 final long origId = Binder.clearCallingIdentity();
9407 ComponentName res = startServiceLocked(null, service,
9408 resolvedType, -1, uid);
9409 Binder.restoreCallingIdentity(origId);
9410 return res;
9411 }
9412 }
9413
9414 public int stopService(IApplicationThread caller, Intent service,
9415 String resolvedType) {
9416 // Refuse possible leaked file descriptors
9417 if (service != null && service.hasFileDescriptors() == true) {
9418 throw new IllegalArgumentException("File descriptors passed in Intent");
9419 }
9420
9421 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009422 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009423 + " type=" + resolvedType);
9424
9425 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9426 if (caller != null && callerApp == null) {
9427 throw new SecurityException(
9428 "Unable to find app for caller " + caller
9429 + " (pid=" + Binder.getCallingPid()
9430 + ") when stopping service " + service);
9431 }
9432
9433 // If this service is active, make sure it is stopped.
9434 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9435 if (r != null) {
9436 if (r.record != null) {
9437 synchronized (r.record.stats.getBatteryStats()) {
9438 r.record.stats.stopRunningLocked();
9439 }
9440 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009441 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009442 final long origId = Binder.clearCallingIdentity();
9443 bringDownServiceLocked(r.record, false);
9444 Binder.restoreCallingIdentity(origId);
9445 return 1;
9446 }
9447 return -1;
9448 }
9449 }
9450
9451 return 0;
9452 }
9453
9454 public IBinder peekService(Intent service, String resolvedType) {
9455 // Refuse possible leaked file descriptors
9456 if (service != null && service.hasFileDescriptors() == true) {
9457 throw new IllegalArgumentException("File descriptors passed in Intent");
9458 }
9459
9460 IBinder ret = null;
9461
9462 synchronized(this) {
9463 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9464
9465 if (r != null) {
9466 // r.record is null if findServiceLocked() failed the caller permission check
9467 if (r.record == null) {
9468 throw new SecurityException(
9469 "Permission Denial: Accessing service " + r.record.name
9470 + " from pid=" + Binder.getCallingPid()
9471 + ", uid=" + Binder.getCallingUid()
9472 + " requires " + r.permission);
9473 }
9474 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9475 if (ib != null) {
9476 ret = ib.binder;
9477 }
9478 }
9479 }
9480
9481 return ret;
9482 }
9483
9484 public boolean stopServiceToken(ComponentName className, IBinder token,
9485 int startId) {
9486 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009487 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009488 + " " + token + " startId=" + startId);
9489 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009490 if (r != null) {
9491 if (startId >= 0) {
9492 // Asked to only stop if done with all work. Note that
9493 // to avoid leaks, we will take this as dropping all
9494 // start items up to and including this one.
9495 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9496 if (si != null) {
9497 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009498 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9499 cur.removeUriPermissionsLocked();
9500 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009501 break;
9502 }
9503 }
9504 }
9505
9506 if (r.lastStartId != startId) {
9507 return false;
9508 }
9509
9510 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009511 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009512 + " is last, but have " + r.deliveredStarts.size()
9513 + " remaining args");
9514 }
9515 }
9516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009517 synchronized (r.stats.getBatteryStats()) {
9518 r.stats.stopRunningLocked();
9519 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009520 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009521 }
9522 final long origId = Binder.clearCallingIdentity();
9523 bringDownServiceLocked(r, false);
9524 Binder.restoreCallingIdentity(origId);
9525 return true;
9526 }
9527 }
9528 return false;
9529 }
9530
9531 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009532 int id, Notification notification, boolean removeNotification) {
9533 final long origId = Binder.clearCallingIdentity();
9534 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009535 synchronized(this) {
9536 ServiceRecord r = findServiceLocked(className, token);
9537 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009538 if (id != 0) {
9539 if (notification == null) {
9540 throw new IllegalArgumentException("null notification");
9541 }
9542 if (r.foregroundId != id) {
9543 r.cancelNotification();
9544 r.foregroundId = id;
9545 }
9546 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9547 r.foregroundNoti = notification;
9548 r.isForeground = true;
9549 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 if (r.app != null) {
9551 updateServiceForegroundLocked(r.app, true);
9552 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009553 } else {
9554 if (r.isForeground) {
9555 r.isForeground = false;
9556 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009557 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009558 updateServiceForegroundLocked(r.app, true);
9559 }
9560 }
9561 if (removeNotification) {
9562 r.cancelNotification();
9563 r.foregroundId = 0;
9564 r.foregroundNoti = null;
9565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009566 }
9567 }
9568 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009569 } finally {
9570 Binder.restoreCallingIdentity(origId);
9571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009572 }
9573
9574 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9575 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009576 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009577 if (sr.isForeground) {
9578 anyForeground = true;
9579 break;
9580 }
9581 }
9582 if (anyForeground != proc.foregroundServices) {
9583 proc.foregroundServices = anyForeground;
9584 if (oomAdj) {
9585 updateOomAdjLocked();
9586 }
9587 }
9588 }
9589
9590 public int bindService(IApplicationThread caller, IBinder token,
9591 Intent service, String resolvedType,
9592 IServiceConnection connection, int flags) {
9593 // Refuse possible leaked file descriptors
9594 if (service != null && service.hasFileDescriptors() == true) {
9595 throw new IllegalArgumentException("File descriptors passed in Intent");
9596 }
9597
9598 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009599 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009600 + " type=" + resolvedType + " conn=" + connection.asBinder()
9601 + " flags=0x" + Integer.toHexString(flags));
9602 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9603 if (callerApp == null) {
9604 throw new SecurityException(
9605 "Unable to find app for caller " + caller
9606 + " (pid=" + Binder.getCallingPid()
9607 + ") when binding service " + service);
9608 }
9609
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009610 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009611 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009612 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009613 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009614 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009615 return 0;
9616 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009617 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009618 }
9619
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009620 int clientLabel = 0;
9621 PendingIntent clientIntent = null;
9622
9623 if (callerApp.info.uid == Process.SYSTEM_UID) {
9624 // Hacky kind of thing -- allow system stuff to tell us
9625 // what they are, so we can report this elsewhere for
9626 // others to know why certain services are running.
9627 try {
9628 clientIntent = (PendingIntent)service.getParcelableExtra(
9629 Intent.EXTRA_CLIENT_INTENT);
9630 } catch (RuntimeException e) {
9631 }
9632 if (clientIntent != null) {
9633 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9634 if (clientLabel != 0) {
9635 // There are no useful extras in the intent, trash them.
9636 // System code calling with this stuff just needs to know
9637 // this will happen.
9638 service = service.cloneFilter();
9639 }
9640 }
9641 }
9642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 ServiceLookupResult res =
9644 retrieveServiceLocked(service, resolvedType,
9645 Binder.getCallingPid(), Binder.getCallingUid());
9646 if (res == null) {
9647 return 0;
9648 }
9649 if (res.record == null) {
9650 return -1;
9651 }
9652 ServiceRecord s = res.record;
9653
9654 final long origId = Binder.clearCallingIdentity();
9655
9656 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009657 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009658 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009659 }
9660
9661 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9662 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009663 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009664
9665 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009666 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9667 if (clist == null) {
9668 clist = new ArrayList<ConnectionRecord>();
9669 s.connections.put(binder, clist);
9670 }
9671 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009672 b.connections.add(c);
9673 if (activity != null) {
9674 if (activity.connections == null) {
9675 activity.connections = new HashSet<ConnectionRecord>();
9676 }
9677 activity.connections.add(c);
9678 }
9679 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009680 clist = mServiceConnections.get(binder);
9681 if (clist == null) {
9682 clist = new ArrayList<ConnectionRecord>();
9683 mServiceConnections.put(binder, clist);
9684 }
9685 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009686
9687 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9688 s.lastActivity = SystemClock.uptimeMillis();
9689 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9690 return 0;
9691 }
9692 }
9693
9694 if (s.app != null) {
9695 // This could have made the service more important.
9696 updateOomAdjLocked(s.app);
9697 }
9698
Joe Onorato8a9b2202010-02-26 18:56:32 -08009699 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700 + ": received=" + b.intent.received
9701 + " apps=" + b.intent.apps.size()
9702 + " doRebind=" + b.intent.doRebind);
9703
9704 if (s.app != null && b.intent.received) {
9705 // Service is already running, so we can immediately
9706 // publish the connection.
9707 try {
9708 c.conn.connected(s.name, b.intent.binder);
9709 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009710 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009711 + " to connection " + c.conn.asBinder()
9712 + " (in " + c.binding.client.processName + ")", e);
9713 }
9714
9715 // If this is the first app connected back to this binding,
9716 // and the service had previously asked to be told when
9717 // rebound, then do so.
9718 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9719 requestServiceBindingLocked(s, b.intent, true);
9720 }
9721 } else if (!b.intent.requested) {
9722 requestServiceBindingLocked(s, b.intent, false);
9723 }
9724
9725 Binder.restoreCallingIdentity(origId);
9726 }
9727
9728 return 1;
9729 }
9730
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009731 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009732 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009733 IBinder binder = c.conn.asBinder();
9734 AppBindRecord b = c.binding;
9735 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009736 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9737 if (clist != null) {
9738 clist.remove(c);
9739 if (clist.size() == 0) {
9740 s.connections.remove(binder);
9741 }
9742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009743 b.connections.remove(c);
9744 if (c.activity != null && c.activity != skipAct) {
9745 if (c.activity.connections != null) {
9746 c.activity.connections.remove(c);
9747 }
9748 }
9749 if (b.client != skipApp) {
9750 b.client.connections.remove(c);
9751 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009752 clist = mServiceConnections.get(binder);
9753 if (clist != null) {
9754 clist.remove(c);
9755 if (clist.size() == 0) {
9756 mServiceConnections.remove(binder);
9757 }
9758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009759
9760 if (b.connections.size() == 0) {
9761 b.intent.apps.remove(b.client);
9762 }
9763
Joe Onorato8a9b2202010-02-26 18:56:32 -08009764 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765 + ": shouldUnbind=" + b.intent.hasBound);
9766 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9767 && b.intent.hasBound) {
9768 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009769 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009770 updateOomAdjLocked(s.app);
9771 b.intent.hasBound = false;
9772 // Assume the client doesn't want to know about a rebind;
9773 // we will deal with that later if it asks for one.
9774 b.intent.doRebind = false;
9775 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9776 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009777 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009778 serviceDoneExecutingLocked(s, true);
9779 }
9780 }
9781
9782 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9783 bringDownServiceLocked(s, false);
9784 }
9785 }
9786
9787 public boolean unbindService(IServiceConnection connection) {
9788 synchronized (this) {
9789 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009790 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009791 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9792 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009793 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794 + connection.asBinder());
9795 return false;
9796 }
9797
9798 final long origId = Binder.clearCallingIdentity();
9799
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009800 while (clist.size() > 0) {
9801 ConnectionRecord r = clist.get(0);
9802 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009803
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009804 if (r.binding.service.app != null) {
9805 // This could have made the service less important.
9806 updateOomAdjLocked(r.binding.service.app);
9807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009808 }
9809
9810 Binder.restoreCallingIdentity(origId);
9811 }
9812
9813 return true;
9814 }
9815
9816 public void publishService(IBinder token, Intent intent, IBinder service) {
9817 // Refuse possible leaked file descriptors
9818 if (intent != null && intent.hasFileDescriptors() == true) {
9819 throw new IllegalArgumentException("File descriptors passed in Intent");
9820 }
9821
9822 synchronized(this) {
9823 if (!(token instanceof ServiceRecord)) {
9824 throw new IllegalArgumentException("Invalid service token");
9825 }
9826 ServiceRecord r = (ServiceRecord)token;
9827
9828 final long origId = Binder.clearCallingIdentity();
9829
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009830 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009831 + " " + intent + ": " + service);
9832 if (r != null) {
9833 Intent.FilterComparison filter
9834 = new Intent.FilterComparison(intent);
9835 IntentBindRecord b = r.bindings.get(filter);
9836 if (b != null && !b.received) {
9837 b.binder = service;
9838 b.requested = true;
9839 b.received = true;
9840 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009841 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009842 = r.connections.values().iterator();
9843 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009844 ArrayList<ConnectionRecord> clist = it.next();
9845 for (int i=0; i<clist.size(); i++) {
9846 ConnectionRecord c = clist.get(i);
9847 if (!filter.equals(c.binding.intent.intent)) {
9848 if (DEBUG_SERVICE) Slog.v(
9849 TAG, "Not publishing to: " + c);
9850 if (DEBUG_SERVICE) Slog.v(
9851 TAG, "Bound intent: " + c.binding.intent.intent);
9852 if (DEBUG_SERVICE) Slog.v(
9853 TAG, "Published intent: " + intent);
9854 continue;
9855 }
9856 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9857 try {
9858 c.conn.connected(r.name, service);
9859 } catch (Exception e) {
9860 Slog.w(TAG, "Failure sending service " + r.name +
9861 " to connection " + c.conn.asBinder() +
9862 " (in " + c.binding.client.processName + ")", e);
9863 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009864 }
9865 }
9866 }
9867 }
9868
9869 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9870
9871 Binder.restoreCallingIdentity(origId);
9872 }
9873 }
9874 }
9875
9876 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9877 // Refuse possible leaked file descriptors
9878 if (intent != null && intent.hasFileDescriptors() == true) {
9879 throw new IllegalArgumentException("File descriptors passed in Intent");
9880 }
9881
9882 synchronized(this) {
9883 if (!(token instanceof ServiceRecord)) {
9884 throw new IllegalArgumentException("Invalid service token");
9885 }
9886 ServiceRecord r = (ServiceRecord)token;
9887
9888 final long origId = Binder.clearCallingIdentity();
9889
9890 if (r != null) {
9891 Intent.FilterComparison filter
9892 = new Intent.FilterComparison(intent);
9893 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009894 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009895 + " at " + b + ": apps="
9896 + (b != null ? b.apps.size() : 0));
9897 if (b != null) {
9898 if (b.apps.size() > 0) {
9899 // Applications have already bound since the last
9900 // unbind, so just rebind right here.
9901 requestServiceBindingLocked(r, b, true);
9902 } else {
9903 // Note to tell the service the next time there is
9904 // a new client.
9905 b.doRebind = true;
9906 }
9907 }
9908
9909 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9910
9911 Binder.restoreCallingIdentity(origId);
9912 }
9913 }
9914 }
9915
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009916 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009917 synchronized(this) {
9918 if (!(token instanceof ServiceRecord)) {
9919 throw new IllegalArgumentException("Invalid service token");
9920 }
9921 ServiceRecord r = (ServiceRecord)token;
9922 boolean inStopping = mStoppingServices.contains(token);
9923 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009924 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009925 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009926 + " with incorrect token: given " + token
9927 + ", expected " + r);
9928 return;
9929 }
9930
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009931 if (type == 1) {
9932 // This is a call from a service start... take care of
9933 // book-keeping.
9934 r.callStart = true;
9935 switch (res) {
9936 case Service.START_STICKY_COMPATIBILITY:
9937 case Service.START_STICKY: {
9938 // We are done with the associated start arguments.
9939 r.findDeliveredStart(startId, true);
9940 // Don't stop if killed.
9941 r.stopIfKilled = false;
9942 break;
9943 }
9944 case Service.START_NOT_STICKY: {
9945 // We are done with the associated start arguments.
9946 r.findDeliveredStart(startId, true);
9947 if (r.lastStartId == startId) {
9948 // There is no more work, and this service
9949 // doesn't want to hang around if killed.
9950 r.stopIfKilled = true;
9951 }
9952 break;
9953 }
9954 case Service.START_REDELIVER_INTENT: {
9955 // We'll keep this item until they explicitly
9956 // call stop for it, but keep track of the fact
9957 // that it was delivered.
9958 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9959 if (si != null) {
9960 si.deliveryCount = 0;
9961 si.doneExecutingCount++;
9962 // Don't stop if killed.
9963 r.stopIfKilled = true;
9964 }
9965 break;
9966 }
9967 default:
9968 throw new IllegalArgumentException(
9969 "Unknown service start result: " + res);
9970 }
9971 if (res == Service.START_STICKY_COMPATIBILITY) {
9972 r.callStart = false;
9973 }
9974 }
9975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 final long origId = Binder.clearCallingIdentity();
9977 serviceDoneExecutingLocked(r, inStopping);
9978 Binder.restoreCallingIdentity(origId);
9979 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009980 Slog.w(TAG, "Done executing unknown service from pid "
9981 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009982 }
9983 }
9984 }
9985
9986 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009987 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9988 + ": nesting=" + r.executeNesting
9989 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009990 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009991 r.executeNesting--;
9992 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009993 if (DEBUG_SERVICE) Slog.v(TAG,
9994 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009995 r.app.executingServices.remove(r);
9996 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009997 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9998 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009999 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10000 }
10001 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010002 if (DEBUG_SERVICE) Slog.v(TAG,
10003 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010004 mStoppingServices.remove(r);
10005 }
10006 updateOomAdjLocked(r.app);
10007 }
10008 }
10009
10010 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010011 String anrMessage = null;
10012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010013 synchronized(this) {
10014 if (proc.executingServices.size() == 0 || proc.thread == null) {
10015 return;
10016 }
10017 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10018 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10019 ServiceRecord timeout = null;
10020 long nextTime = 0;
10021 while (it.hasNext()) {
10022 ServiceRecord sr = it.next();
10023 if (sr.executingStart < maxTime) {
10024 timeout = sr;
10025 break;
10026 }
10027 if (sr.executingStart > nextTime) {
10028 nextTime = sr.executingStart;
10029 }
10030 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010031 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010032 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010033 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010034 } else {
10035 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10036 msg.obj = proc;
10037 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10038 }
10039 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010040
10041 if (anrMessage != null) {
10042 appNotResponding(proc, null, null, anrMessage);
10043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010044 }
10045
10046 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010047 // BACKUP AND RESTORE
10048 // =========================================================
10049
10050 // Cause the target app to be launched if necessary and its backup agent
10051 // instantiated. The backup agent will invoke backupAgentCreated() on the
10052 // activity manager to announce its creation.
10053 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010054 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010055 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10056
10057 synchronized(this) {
10058 // !!! TODO: currently no check here that we're already bound
10059 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10060 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10061 synchronized (stats) {
10062 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10063 }
10064
10065 BackupRecord r = new BackupRecord(ss, app, backupMode);
10066 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10067 // startProcessLocked() returns existing proc's record if it's already running
10068 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010069 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010070 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010071 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010072 return false;
10073 }
10074
10075 r.app = proc;
10076 mBackupTarget = r;
10077 mBackupAppName = app.packageName;
10078
Christopher Tate6fa95972009-06-05 18:43:55 -070010079 // Try not to kill the process during backup
10080 updateOomAdjLocked(proc);
10081
Christopher Tate181fafa2009-05-14 11:12:14 -070010082 // If the process is already attached, schedule the creation of the backup agent now.
10083 // If it is not yet live, this will be done when it attaches to the framework.
10084 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010085 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010086 try {
10087 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10088 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010089 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010090 }
10091 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010092 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010093 }
10094 // Invariants: at this point, the target app process exists and the application
10095 // is either already running or in the process of coming up. mBackupTarget and
10096 // mBackupAppName describe the app, so that when it binds back to the AM we
10097 // know that it's scheduled for a backup-agent operation.
10098 }
10099
10100 return true;
10101 }
10102
10103 // A backup agent has just come up
10104 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010105 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010106 + " = " + agent);
10107
10108 synchronized(this) {
10109 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010110 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010111 return;
10112 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010113 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010114
Dianne Hackborn06740692010-09-22 22:46:21 -070010115 long oldIdent = Binder.clearCallingIdentity();
10116 try {
10117 IBackupManager bm = IBackupManager.Stub.asInterface(
10118 ServiceManager.getService(Context.BACKUP_SERVICE));
10119 bm.agentConnected(agentPackageName, agent);
10120 } catch (RemoteException e) {
10121 // can't happen; the backup manager service is local
10122 } catch (Exception e) {
10123 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10124 e.printStackTrace();
10125 } finally {
10126 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010127 }
10128 }
10129
10130 // done with this agent
10131 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010132 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010133 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010134 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010135 return;
10136 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010137
10138 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010139 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010140 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010141 return;
10142 }
10143
Christopher Tate181fafa2009-05-14 11:12:14 -070010144 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010145 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010146 return;
10147 }
10148
Christopher Tate6fa95972009-06-05 18:43:55 -070010149 ProcessRecord proc = mBackupTarget.app;
10150 mBackupTarget = null;
10151 mBackupAppName = null;
10152
10153 // Not backing this app up any more; reset its OOM adjustment
10154 updateOomAdjLocked(proc);
10155
Christopher Tatec7b31e32009-06-10 15:49:30 -070010156 // If the app crashed during backup, 'thread' will be null here
10157 if (proc.thread != null) {
10158 try {
10159 proc.thread.scheduleDestroyBackupAgent(appInfo);
10160 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010161 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010162 e.printStackTrace();
10163 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010164 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010165 }
10166 }
10167 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010168 // BROADCASTS
10169 // =========================================================
10170
Josh Bartel7f208742010-02-25 11:01:44 -060010171 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010172 List cur) {
10173 final ContentResolver resolver = mContext.getContentResolver();
10174 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10175 if (list == null) {
10176 return cur;
10177 }
10178 int N = list.size();
10179 for (int i=0; i<N; i++) {
10180 Intent intent = list.get(i);
10181 if (filter.match(resolver, intent, true, TAG) >= 0) {
10182 if (cur == null) {
10183 cur = new ArrayList<Intent>();
10184 }
10185 cur.add(intent);
10186 }
10187 }
10188 return cur;
10189 }
10190
10191 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010192 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010193 + mBroadcastsScheduled);
10194
10195 if (mBroadcastsScheduled) {
10196 return;
10197 }
10198 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10199 mBroadcastsScheduled = true;
10200 }
10201
10202 public Intent registerReceiver(IApplicationThread caller,
10203 IIntentReceiver receiver, IntentFilter filter, String permission) {
10204 synchronized(this) {
10205 ProcessRecord callerApp = null;
10206 if (caller != null) {
10207 callerApp = getRecordForAppLocked(caller);
10208 if (callerApp == null) {
10209 throw new SecurityException(
10210 "Unable to find app for caller " + caller
10211 + " (pid=" + Binder.getCallingPid()
10212 + ") when registering receiver " + receiver);
10213 }
10214 }
10215
10216 List allSticky = null;
10217
10218 // Look for any matching sticky broadcasts...
10219 Iterator actions = filter.actionsIterator();
10220 if (actions != null) {
10221 while (actions.hasNext()) {
10222 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010223 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010224 }
10225 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010226 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010227 }
10228
10229 // The first sticky in the list is returned directly back to
10230 // the client.
10231 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10232
Joe Onorato8a9b2202010-02-26 18:56:32 -080010233 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234 + ": " + sticky);
10235
10236 if (receiver == null) {
10237 return sticky;
10238 }
10239
10240 ReceiverList rl
10241 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10242 if (rl == null) {
10243 rl = new ReceiverList(this, callerApp,
10244 Binder.getCallingPid(),
10245 Binder.getCallingUid(), receiver);
10246 if (rl.app != null) {
10247 rl.app.receivers.add(rl);
10248 } else {
10249 try {
10250 receiver.asBinder().linkToDeath(rl, 0);
10251 } catch (RemoteException e) {
10252 return sticky;
10253 }
10254 rl.linkedToDeath = true;
10255 }
10256 mRegisteredReceivers.put(receiver.asBinder(), rl);
10257 }
10258 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10259 rl.add(bf);
10260 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010261 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010262 }
10263 mReceiverResolver.addFilter(bf);
10264
10265 // Enqueue broadcasts for all existing stickies that match
10266 // this filter.
10267 if (allSticky != null) {
10268 ArrayList receivers = new ArrayList();
10269 receivers.add(bf);
10270
10271 int N = allSticky.size();
10272 for (int i=0; i<N; i++) {
10273 Intent intent = (Intent)allSticky.get(i);
10274 BroadcastRecord r = new BroadcastRecord(intent, null,
10275 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010276 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010277 if (mParallelBroadcasts.size() == 0) {
10278 scheduleBroadcastsLocked();
10279 }
10280 mParallelBroadcasts.add(r);
10281 }
10282 }
10283
10284 return sticky;
10285 }
10286 }
10287
10288 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010289 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010290
10291 boolean doNext = false;
10292
10293 synchronized(this) {
10294 ReceiverList rl
10295 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10296 if (rl != null) {
10297 if (rl.curBroadcast != null) {
10298 BroadcastRecord r = rl.curBroadcast;
10299 doNext = finishReceiverLocked(
10300 receiver.asBinder(), r.resultCode, r.resultData,
10301 r.resultExtras, r.resultAbort, true);
10302 }
10303
10304 if (rl.app != null) {
10305 rl.app.receivers.remove(rl);
10306 }
10307 removeReceiverLocked(rl);
10308 if (rl.linkedToDeath) {
10309 rl.linkedToDeath = false;
10310 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10311 }
10312 }
10313 }
10314
10315 if (!doNext) {
10316 return;
10317 }
10318
10319 final long origId = Binder.clearCallingIdentity();
10320 processNextBroadcast(false);
10321 trimApplications();
10322 Binder.restoreCallingIdentity(origId);
10323 }
10324
10325 void removeReceiverLocked(ReceiverList rl) {
10326 mRegisteredReceivers.remove(rl.receiver.asBinder());
10327 int N = rl.size();
10328 for (int i=0; i<N; i++) {
10329 mReceiverResolver.removeFilter(rl.get(i));
10330 }
10331 }
10332
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010333 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10334 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10335 ProcessRecord r = mLruProcesses.get(i);
10336 if (r.thread != null) {
10337 try {
10338 r.thread.dispatchPackageBroadcast(cmd, packages);
10339 } catch (RemoteException ex) {
10340 }
10341 }
10342 }
10343 }
10344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010345 private final int broadcastIntentLocked(ProcessRecord callerApp,
10346 String callerPackage, Intent intent, String resolvedType,
10347 IIntentReceiver resultTo, int resultCode, String resultData,
10348 Bundle map, String requiredPermission,
10349 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10350 intent = new Intent(intent);
10351
Joe Onorato8a9b2202010-02-26 18:56:32 -080010352 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010353 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10354 + " ordered=" + ordered);
10355 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010356 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 }
10358
10359 // Handle special intents: if this broadcast is from the package
10360 // manager about a package being removed, we need to remove all of
10361 // its activities from the history stack.
10362 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10363 intent.getAction());
10364 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10365 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010366 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367 || uidRemoved) {
10368 if (checkComponentPermission(
10369 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10370 callingPid, callingUid, -1)
10371 == PackageManager.PERMISSION_GRANTED) {
10372 if (uidRemoved) {
10373 final Bundle intentExtras = intent.getExtras();
10374 final int uid = intentExtras != null
10375 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10376 if (uid >= 0) {
10377 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10378 synchronized (bs) {
10379 bs.removeUidStatsLocked(uid);
10380 }
10381 }
10382 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010383 // If resources are unvailble just force stop all
10384 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010385 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010386 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10387 if (list != null && (list.length > 0)) {
10388 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010389 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010390 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010391 sendPackageBroadcastLocked(
10392 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010393 }
10394 } else {
10395 Uri data = intent.getData();
10396 String ssp;
10397 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10398 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10399 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010400 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010401 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010402 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10403 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10404 new String[] {ssp});
10405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010406 }
10407 }
10408 }
10409 } else {
10410 String msg = "Permission Denial: " + intent.getAction()
10411 + " broadcast from " + callerPackage + " (pid=" + callingPid
10412 + ", uid=" + callingUid + ")"
10413 + " requires "
10414 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010415 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010416 throw new SecurityException(msg);
10417 }
10418 }
10419
10420 /*
10421 * If this is the time zone changed action, queue up a message that will reset the timezone
10422 * of all currently running processes. This message will get queued up before the broadcast
10423 * happens.
10424 */
10425 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10426 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10427 }
10428
Robert Greenwalt03595d02010-11-02 14:08:23 -070010429 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10430 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10431 }
10432
Robert Greenwalt434203a2010-10-11 16:00:27 -070010433 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10434 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10435 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10436 }
10437
Dianne Hackborn854060af2009-07-09 18:14:31 -070010438 /*
10439 * Prevent non-system code (defined here to be non-persistent
10440 * processes) from sending protected broadcasts.
10441 */
10442 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10443 || callingUid == Process.SHELL_UID || callingUid == 0) {
10444 // Always okay.
10445 } else if (callerApp == null || !callerApp.persistent) {
10446 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010447 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010448 intent.getAction())) {
10449 String msg = "Permission Denial: not allowed to send broadcast "
10450 + intent.getAction() + " from pid="
10451 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010452 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010453 throw new SecurityException(msg);
10454 }
10455 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010456 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010457 return BROADCAST_SUCCESS;
10458 }
10459 }
10460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010461 // Add to the sticky list if requested.
10462 if (sticky) {
10463 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10464 callingPid, callingUid)
10465 != PackageManager.PERMISSION_GRANTED) {
10466 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10467 + callingPid + ", uid=" + callingUid
10468 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010469 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010470 throw new SecurityException(msg);
10471 }
10472 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010473 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010474 + " and enforce permission " + requiredPermission);
10475 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10476 }
10477 if (intent.getComponent() != null) {
10478 throw new SecurityException(
10479 "Sticky broadcasts can't target a specific component");
10480 }
10481 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10482 if (list == null) {
10483 list = new ArrayList<Intent>();
10484 mStickyBroadcasts.put(intent.getAction(), list);
10485 }
10486 int N = list.size();
10487 int i;
10488 for (i=0; i<N; i++) {
10489 if (intent.filterEquals(list.get(i))) {
10490 // This sticky already exists, replace it.
10491 list.set(i, new Intent(intent));
10492 break;
10493 }
10494 }
10495 if (i >= N) {
10496 list.add(new Intent(intent));
10497 }
10498 }
10499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010500 // Figure out who all will receive this broadcast.
10501 List receivers = null;
10502 List<BroadcastFilter> registeredReceivers = null;
10503 try {
10504 if (intent.getComponent() != null) {
10505 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010506 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010507 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010508 if (ai != null) {
10509 receivers = new ArrayList();
10510 ResolveInfo ri = new ResolveInfo();
10511 ri.activityInfo = ai;
10512 receivers.add(ri);
10513 }
10514 } else {
10515 // Need to resolve the intent to interested receivers...
10516 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10517 == 0) {
10518 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010519 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010520 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010521 }
Mihai Preda074edef2009-05-18 17:13:31 +020010522 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010523 }
10524 } catch (RemoteException ex) {
10525 // pm is in same process, this will never happen.
10526 }
10527
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010528 final boolean replacePending =
10529 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10530
Joe Onorato8a9b2202010-02-26 18:56:32 -080010531 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010532 + " replacePending=" + replacePending);
10533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010534 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10535 if (!ordered && NR > 0) {
10536 // If we are not serializing this broadcast, then send the
10537 // registered receivers separately so they don't wait for the
10538 // components to be launched.
10539 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10540 callerPackage, callingPid, callingUid, requiredPermission,
10541 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010542 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010543 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010544 TAG, "Enqueueing parallel broadcast " + r
10545 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010546 boolean replaced = false;
10547 if (replacePending) {
10548 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10549 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010550 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010551 "***** DROPPING PARALLEL: " + intent);
10552 mParallelBroadcasts.set(i, r);
10553 replaced = true;
10554 break;
10555 }
10556 }
10557 }
10558 if (!replaced) {
10559 mParallelBroadcasts.add(r);
10560 scheduleBroadcastsLocked();
10561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010562 registeredReceivers = null;
10563 NR = 0;
10564 }
10565
10566 // Merge into one list.
10567 int ir = 0;
10568 if (receivers != null) {
10569 // A special case for PACKAGE_ADDED: do not allow the package
10570 // being added to see this broadcast. This prevents them from
10571 // using this as a back door to get run as soon as they are
10572 // installed. Maybe in the future we want to have a special install
10573 // broadcast or such for apps, but we'd like to deliberately make
10574 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010575 String skipPackages[] = null;
10576 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10577 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10578 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10579 Uri data = intent.getData();
10580 if (data != null) {
10581 String pkgName = data.getSchemeSpecificPart();
10582 if (pkgName != null) {
10583 skipPackages = new String[] { pkgName };
10584 }
10585 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010586 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010587 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010588 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010589 if (skipPackages != null && (skipPackages.length > 0)) {
10590 for (String skipPackage : skipPackages) {
10591 if (skipPackage != null) {
10592 int NT = receivers.size();
10593 for (int it=0; it<NT; it++) {
10594 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10595 if (curt.activityInfo.packageName.equals(skipPackage)) {
10596 receivers.remove(it);
10597 it--;
10598 NT--;
10599 }
10600 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010601 }
10602 }
10603 }
10604
10605 int NT = receivers != null ? receivers.size() : 0;
10606 int it = 0;
10607 ResolveInfo curt = null;
10608 BroadcastFilter curr = null;
10609 while (it < NT && ir < NR) {
10610 if (curt == null) {
10611 curt = (ResolveInfo)receivers.get(it);
10612 }
10613 if (curr == null) {
10614 curr = registeredReceivers.get(ir);
10615 }
10616 if (curr.getPriority() >= curt.priority) {
10617 // Insert this broadcast record into the final list.
10618 receivers.add(it, curr);
10619 ir++;
10620 curr = null;
10621 it++;
10622 NT++;
10623 } else {
10624 // Skip to the next ResolveInfo in the final list.
10625 it++;
10626 curt = null;
10627 }
10628 }
10629 }
10630 while (ir < NR) {
10631 if (receivers == null) {
10632 receivers = new ArrayList();
10633 }
10634 receivers.add(registeredReceivers.get(ir));
10635 ir++;
10636 }
10637
10638 if ((receivers != null && receivers.size() > 0)
10639 || resultTo != null) {
10640 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10641 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010642 receivers, resultTo, resultCode, resultData, map, ordered,
10643 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010644 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010645 TAG, "Enqueueing ordered broadcast " + r
10646 + ": prev had " + mOrderedBroadcasts.size());
10647 if (DEBUG_BROADCAST) {
10648 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010649 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010650 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010651 boolean replaced = false;
10652 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010653 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010654 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010655 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010656 "***** DROPPING ORDERED: " + intent);
10657 mOrderedBroadcasts.set(i, r);
10658 replaced = true;
10659 break;
10660 }
10661 }
10662 }
10663 if (!replaced) {
10664 mOrderedBroadcasts.add(r);
10665 scheduleBroadcastsLocked();
10666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667 }
10668
10669 return BROADCAST_SUCCESS;
10670 }
10671
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010672 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010673 // Refuse possible leaked file descriptors
10674 if (intent != null && intent.hasFileDescriptors() == true) {
10675 throw new IllegalArgumentException("File descriptors passed in Intent");
10676 }
10677
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010678 int flags = intent.getFlags();
10679
10680 if (!mProcessesReady) {
10681 // if the caller really truly claims to know what they're doing, go
10682 // ahead and allow the broadcast without launching any receivers
10683 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10684 intent = new Intent(intent);
10685 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10686 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10687 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10688 + " before boot completion");
10689 throw new IllegalStateException("Cannot broadcast before boot completed");
10690 }
10691 }
10692
10693 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10694 throw new IllegalArgumentException(
10695 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10696 }
10697
10698 return intent;
10699 }
10700
10701 public final int broadcastIntent(IApplicationThread caller,
10702 Intent intent, String resolvedType, IIntentReceiver resultTo,
10703 int resultCode, String resultData, Bundle map,
10704 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010705 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010706 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010708 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10709 final int callingPid = Binder.getCallingPid();
10710 final int callingUid = Binder.getCallingUid();
10711 final long origId = Binder.clearCallingIdentity();
10712 int res = broadcastIntentLocked(callerApp,
10713 callerApp != null ? callerApp.info.packageName : null,
10714 intent, resolvedType, resultTo,
10715 resultCode, resultData, map, requiredPermission, serialized,
10716 sticky, callingPid, callingUid);
10717 Binder.restoreCallingIdentity(origId);
10718 return res;
10719 }
10720 }
10721
10722 int broadcastIntentInPackage(String packageName, int uid,
10723 Intent intent, String resolvedType, IIntentReceiver resultTo,
10724 int resultCode, String resultData, Bundle map,
10725 String requiredPermission, boolean serialized, boolean sticky) {
10726 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010727 intent = verifyBroadcastLocked(intent);
10728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010729 final long origId = Binder.clearCallingIdentity();
10730 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10731 resultTo, resultCode, resultData, map, requiredPermission,
10732 serialized, sticky, -1, uid);
10733 Binder.restoreCallingIdentity(origId);
10734 return res;
10735 }
10736 }
10737
10738 public final void unbroadcastIntent(IApplicationThread caller,
10739 Intent intent) {
10740 // Refuse possible leaked file descriptors
10741 if (intent != null && intent.hasFileDescriptors() == true) {
10742 throw new IllegalArgumentException("File descriptors passed in Intent");
10743 }
10744
10745 synchronized(this) {
10746 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10747 != PackageManager.PERMISSION_GRANTED) {
10748 String msg = "Permission Denial: unbroadcastIntent() from pid="
10749 + Binder.getCallingPid()
10750 + ", uid=" + Binder.getCallingUid()
10751 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010752 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753 throw new SecurityException(msg);
10754 }
10755 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10756 if (list != null) {
10757 int N = list.size();
10758 int i;
10759 for (i=0; i<N; i++) {
10760 if (intent.filterEquals(list.get(i))) {
10761 list.remove(i);
10762 break;
10763 }
10764 }
10765 }
10766 }
10767 }
10768
10769 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10770 String resultData, Bundle resultExtras, boolean resultAbort,
10771 boolean explicit) {
10772 if (mOrderedBroadcasts.size() == 0) {
10773 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010774 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010775 }
10776 return false;
10777 }
10778 BroadcastRecord r = mOrderedBroadcasts.get(0);
10779 if (r.receiver == null) {
10780 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010781 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 }
10783 return false;
10784 }
10785 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010786 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010787 return false;
10788 }
10789 int state = r.state;
10790 r.state = r.IDLE;
10791 if (state == r.IDLE) {
10792 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010793 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010794 }
10795 }
10796 r.receiver = null;
10797 r.intent.setComponent(null);
10798 if (r.curApp != null) {
10799 r.curApp.curReceiver = null;
10800 }
10801 if (r.curFilter != null) {
10802 r.curFilter.receiverList.curBroadcast = null;
10803 }
10804 r.curFilter = null;
10805 r.curApp = null;
10806 r.curComponent = null;
10807 r.curReceiver = null;
10808 mPendingBroadcast = null;
10809
10810 r.resultCode = resultCode;
10811 r.resultData = resultData;
10812 r.resultExtras = resultExtras;
10813 r.resultAbort = resultAbort;
10814
10815 // We will process the next receiver right now if this is finishing
10816 // an app receiver (which is always asynchronous) or after we have
10817 // come back from calling a receiver.
10818 return state == BroadcastRecord.APP_RECEIVE
10819 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10820 }
10821
10822 public void finishReceiver(IBinder who, int resultCode, String resultData,
10823 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010824 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010825
10826 // Refuse possible leaked file descriptors
10827 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10828 throw new IllegalArgumentException("File descriptors passed in Bundle");
10829 }
10830
10831 boolean doNext;
10832
10833 final long origId = Binder.clearCallingIdentity();
10834
10835 synchronized(this) {
10836 doNext = finishReceiverLocked(
10837 who, resultCode, resultData, resultExtras, resultAbort, true);
10838 }
10839
10840 if (doNext) {
10841 processNextBroadcast(false);
10842 }
10843 trimApplications();
10844
10845 Binder.restoreCallingIdentity(origId);
10846 }
10847
Jeff Brown4d94a762010-09-23 11:33:28 -070010848 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010849 if (r.nextReceiver > 0) {
10850 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10851 if (curReceiver instanceof BroadcastFilter) {
10852 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010853 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010854 System.identityHashCode(r),
10855 r.intent.getAction(),
10856 r.nextReceiver - 1,
10857 System.identityHashCode(bf));
10858 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010859 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010860 System.identityHashCode(r),
10861 r.intent.getAction(),
10862 r.nextReceiver - 1,
10863 ((ResolveInfo)curReceiver).toString());
10864 }
10865 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010866 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010867 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010868 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010869 System.identityHashCode(r),
10870 r.intent.getAction(),
10871 r.nextReceiver,
10872 "NONE");
10873 }
10874 }
10875
Jeff Brown4d94a762010-09-23 11:33:28 -070010876 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10877 if (! mPendingBroadcastTimeoutMessage) {
10878 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10879 mHandler.sendMessageAtTime(msg, timeoutTime);
10880 mPendingBroadcastTimeoutMessage = true;
10881 }
10882 }
10883
10884 private final void cancelBroadcastTimeoutLocked() {
10885 if (mPendingBroadcastTimeoutMessage) {
10886 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10887 mPendingBroadcastTimeoutMessage = false;
10888 }
10889 }
10890
10891 private final void broadcastTimeoutLocked(boolean fromMsg) {
10892 if (fromMsg) {
10893 mPendingBroadcastTimeoutMessage = false;
10894 }
10895
10896 if (mOrderedBroadcasts.size() == 0) {
10897 return;
10898 }
10899
10900 long now = SystemClock.uptimeMillis();
10901 BroadcastRecord r = mOrderedBroadcasts.get(0);
10902 if (fromMsg) {
10903 if (mDidDexOpt) {
10904 // Delay timeouts until dexopt finishes.
10905 mDidDexOpt = false;
10906 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10907 setBroadcastTimeoutLocked(timeoutTime);
10908 return;
10909 }
10910 if (! mProcessesReady) {
10911 // Only process broadcast timeouts if the system is ready. That way
10912 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10913 // to do heavy lifting for system up.
10914 return;
10915 }
10916
10917 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10918 if (timeoutTime > now) {
10919 // We can observe premature timeouts because we do not cancel and reset the
10920 // broadcast timeout message after each receiver finishes. Instead, we set up
10921 // an initial timeout then kick it down the road a little further as needed
10922 // when it expires.
10923 if (DEBUG_BROADCAST) Slog.v(TAG,
10924 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10925 + timeoutTime);
10926 setBroadcastTimeoutLocked(timeoutTime);
10927 return;
10928 }
10929 }
10930
10931 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10932 + ", started " + (now - r.receiverTime) + "ms ago");
10933 r.receiverTime = now;
10934 r.anrCount++;
10935
10936 // Current receiver has passed its expiration date.
10937 if (r.nextReceiver <= 0) {
10938 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10939 return;
10940 }
10941
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010942 ProcessRecord app = null;
10943 String anrMessage = null;
10944
Jeff Brown4d94a762010-09-23 11:33:28 -070010945 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10946 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10947 logBroadcastReceiverDiscardLocked(r);
10948 if (curReceiver instanceof BroadcastFilter) {
10949 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10950 if (bf.receiverList.pid != 0
10951 && bf.receiverList.pid != MY_PID) {
10952 synchronized (this.mPidsSelfLocked) {
10953 app = this.mPidsSelfLocked.get(
10954 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010956 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010957 } else {
10958 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010959 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010960
Jeff Brown4d94a762010-09-23 11:33:28 -070010961 if (app != null) {
10962 anrMessage = "Broadcast of " + r.intent.toString();
10963 }
10964
10965 if (mPendingBroadcast == r) {
10966 mPendingBroadcast = null;
10967 }
10968
10969 // Move on to the next receiver.
10970 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10971 r.resultExtras, r.resultAbort, true);
10972 scheduleBroadcastsLocked();
10973
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010974 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010975 // Post the ANR to the handler since we do not want to process ANRs while
10976 // potentially holding our lock.
10977 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979 }
10980
10981 private final void processCurBroadcastLocked(BroadcastRecord r,
10982 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010983 if (DEBUG_BROADCAST) Slog.v(TAG,
10984 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 if (app.thread == null) {
10986 throw new RemoteException();
10987 }
10988 r.receiver = app.thread.asBinder();
10989 r.curApp = app;
10990 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010991 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992
10993 // Tell the application to launch this receiver.
10994 r.intent.setComponent(r.curComponent);
10995
10996 boolean started = false;
10997 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010998 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010999 "Delivering to component " + r.curComponent
11000 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011001 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011002 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11003 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011004 if (DEBUG_BROADCAST) Slog.v(TAG,
11005 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011006 started = true;
11007 } finally {
11008 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011009 if (DEBUG_BROADCAST) Slog.v(TAG,
11010 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 r.receiver = null;
11012 r.curApp = null;
11013 app.curReceiver = null;
11014 }
11015 }
11016
11017 }
11018
Jeff Brown4d94a762010-09-23 11:33:28 -070011019 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011020 Intent intent, int resultCode, String data, Bundle extras,
11021 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011022 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 if (app != null && app.thread != null) {
11024 // If we have an app thread, do the call through that so it is
11025 // correctly ordered with other one-way calls.
11026 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011027 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011028 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011029 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011030 }
11031 }
11032
Jeff Brown4d94a762010-09-23 11:33:28 -070011033 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011034 BroadcastFilter filter, boolean ordered) {
11035 boolean skip = false;
11036 if (filter.requiredPermission != null) {
11037 int perm = checkComponentPermission(filter.requiredPermission,
11038 r.callingPid, r.callingUid, -1);
11039 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011040 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011041 + r.intent.toString()
11042 + " from " + r.callerPackage + " (pid="
11043 + r.callingPid + ", uid=" + r.callingUid + ")"
11044 + " requires " + filter.requiredPermission
11045 + " due to registered receiver " + filter);
11046 skip = true;
11047 }
11048 }
11049 if (r.requiredPermission != null) {
11050 int perm = checkComponentPermission(r.requiredPermission,
11051 filter.receiverList.pid, filter.receiverList.uid, -1);
11052 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011053 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011054 + r.intent.toString()
11055 + " to " + filter.receiverList.app
11056 + " (pid=" + filter.receiverList.pid
11057 + ", uid=" + filter.receiverList.uid + ")"
11058 + " requires " + r.requiredPermission
11059 + " due to sender " + r.callerPackage
11060 + " (uid " + r.callingUid + ")");
11061 skip = true;
11062 }
11063 }
11064
11065 if (!skip) {
11066 // If this is not being sent as an ordered broadcast, then we
11067 // don't want to touch the fields that keep track of the current
11068 // state of ordered broadcasts.
11069 if (ordered) {
11070 r.receiver = filter.receiverList.receiver.asBinder();
11071 r.curFilter = filter;
11072 filter.receiverList.curBroadcast = r;
11073 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011074 if (filter.receiverList.app != null) {
11075 // Bump hosting application to no longer be in background
11076 // scheduling class. Note that we can't do that if there
11077 // isn't an app... but we can only be in that case for
11078 // things that directly call the IActivityManager API, which
11079 // are already core system stuff so don't matter for this.
11080 r.curApp = filter.receiverList.app;
11081 filter.receiverList.app.curReceiver = r;
11082 updateOomAdjLocked();
11083 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011084 }
11085 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011086 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011088 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011089 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011090 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011091 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011092 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011093 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011094 if (ordered) {
11095 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11096 }
11097 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011098 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011099 if (ordered) {
11100 r.receiver = null;
11101 r.curFilter = null;
11102 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011103 if (filter.receiverList.app != null) {
11104 filter.receiverList.app.curReceiver = null;
11105 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011106 }
11107 }
11108 }
11109 }
11110
Dianne Hackborn12527f92009-11-11 17:39:50 -080011111 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11112 if (r.callingUid < 0) {
11113 // This was from a registerReceiver() call; ignore it.
11114 return;
11115 }
11116 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11117 MAX_BROADCAST_HISTORY-1);
11118 r.finishTime = SystemClock.uptimeMillis();
11119 mBroadcastHistory[0] = r;
11120 }
11121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011122 private final void processNextBroadcast(boolean fromMsg) {
11123 synchronized(this) {
11124 BroadcastRecord r;
11125
Joe Onorato8a9b2202010-02-26 18:56:32 -080011126 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011127 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011128 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011129
11130 updateCpuStats();
11131
11132 if (fromMsg) {
11133 mBroadcastsScheduled = false;
11134 }
11135
11136 // First, deliver any non-serialized broadcasts right away.
11137 while (mParallelBroadcasts.size() > 0) {
11138 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011139 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011140 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011141 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011142 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011143 for (int i=0; i<N; i++) {
11144 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011145 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011146 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011147 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011148 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011149 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011150 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011151 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011152 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011153 }
11154
11155 // Now take care of the next serialized one...
11156
11157 // If we are waiting for a process to come up to handle the next
11158 // broadcast, then do nothing at this point. Just in case, we
11159 // check that the process we're waiting for still exists.
11160 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011161 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011162 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011163 + mPendingBroadcast.curApp);
11164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011165
11166 boolean isDead;
11167 synchronized (mPidsSelfLocked) {
11168 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11169 }
11170 if (!isDead) {
11171 // It's still alive, so keep waiting
11172 return;
11173 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011174 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011175 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011176 mPendingBroadcast.state = BroadcastRecord.IDLE;
11177 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011178 mPendingBroadcast = null;
11179 }
11180 }
11181
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011182 boolean looped = false;
11183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011184 do {
11185 if (mOrderedBroadcasts.size() == 0) {
11186 // No more broadcasts pending, so all done!
11187 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011188 if (looped) {
11189 // If we had finished the last ordered broadcast, then
11190 // make sure all processes have correct oom and sched
11191 // adjustments.
11192 updateOomAdjLocked();
11193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 return;
11195 }
11196 r = mOrderedBroadcasts.get(0);
11197 boolean forceReceive = false;
11198
11199 // Ensure that even if something goes awry with the timeout
11200 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011201 // and continue to make progress.
11202 //
11203 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011204 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011205 // one time heavy lifting after system upgrades and can take
11206 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011207 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011208 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011209 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 if ((numReceivers > 0) &&
11211 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011212 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011213 + " now=" + now
11214 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011215 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011216 + " intent=" + r.intent
11217 + " numReceivers=" + numReceivers
11218 + " nextReceiver=" + r.nextReceiver
11219 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011220 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011221 forceReceive = true;
11222 r.state = BroadcastRecord.IDLE;
11223 }
11224 }
11225
11226 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011227 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011228 "processNextBroadcast() called when not idle (state="
11229 + r.state + ")");
11230 return;
11231 }
11232
11233 if (r.receivers == null || r.nextReceiver >= numReceivers
11234 || r.resultAbort || forceReceive) {
11235 // No more receivers for this broadcast! Send the final
11236 // result if requested...
11237 if (r.resultTo != null) {
11238 try {
11239 if (DEBUG_BROADCAST) {
11240 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011241 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011242 + " seq=" + seq + " app=" + r.callerApp);
11243 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011244 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011245 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011246 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011247 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011248 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011249 }
11250 }
11251
Joe Onorato8a9b2202010-02-26 18:56:32 -080011252 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011253 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011254
Joe Onorato8a9b2202010-02-26 18:56:32 -080011255 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011256 + r);
11257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011259 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011260 mOrderedBroadcasts.remove(0);
11261 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011262 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 continue;
11264 }
11265 } while (r == null);
11266
11267 // Get the next receiver...
11268 int recIdx = r.nextReceiver++;
11269
11270 // Keep track of when this receiver started, and make sure there
11271 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011272 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011273 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011274 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011275
Joe Onorato8a9b2202010-02-26 18:56:32 -080011276 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011277 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011278 }
11279 if (! mPendingBroadcastTimeoutMessage) {
11280 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011281 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011282 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11283 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011284 }
11285
11286 Object nextReceiver = r.receivers.get(recIdx);
11287 if (nextReceiver instanceof BroadcastFilter) {
11288 // Simple case: this is a registered receiver who gets
11289 // a direct call.
11290 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011291 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011292 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011293 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011294 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 if (r.receiver == null || !r.ordered) {
11296 // The receiver has already finished, so schedule to
11297 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011298 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11299 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011300 r.state = BroadcastRecord.IDLE;
11301 scheduleBroadcastsLocked();
11302 }
11303 return;
11304 }
11305
11306 // Hard case: need to instantiate the receiver, possibly
11307 // starting its application process to host it.
11308
11309 ResolveInfo info =
11310 (ResolveInfo)nextReceiver;
11311
11312 boolean skip = false;
11313 int perm = checkComponentPermission(info.activityInfo.permission,
11314 r.callingPid, r.callingUid,
11315 info.activityInfo.exported
11316 ? -1 : info.activityInfo.applicationInfo.uid);
11317 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011318 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011319 + r.intent.toString()
11320 + " from " + r.callerPackage + " (pid=" + r.callingPid
11321 + ", uid=" + r.callingUid + ")"
11322 + " requires " + info.activityInfo.permission
11323 + " due to receiver " + info.activityInfo.packageName
11324 + "/" + info.activityInfo.name);
11325 skip = true;
11326 }
11327 if (r.callingUid != Process.SYSTEM_UID &&
11328 r.requiredPermission != null) {
11329 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011330 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011331 checkPermission(r.requiredPermission,
11332 info.activityInfo.applicationInfo.packageName);
11333 } catch (RemoteException e) {
11334 perm = PackageManager.PERMISSION_DENIED;
11335 }
11336 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011337 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011338 + r.intent + " to "
11339 + info.activityInfo.applicationInfo.packageName
11340 + " requires " + r.requiredPermission
11341 + " due to sender " + r.callerPackage
11342 + " (uid " + r.callingUid + ")");
11343 skip = true;
11344 }
11345 }
11346 if (r.curApp != null && r.curApp.crashing) {
11347 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011348 if (DEBUG_BROADCAST) Slog.v(TAG,
11349 "Skipping deliver ordered " + r + " to " + r.curApp
11350 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011351 skip = true;
11352 }
11353
11354 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011355 if (DEBUG_BROADCAST) Slog.v(TAG,
11356 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 r.receiver = null;
11358 r.curFilter = null;
11359 r.state = BroadcastRecord.IDLE;
11360 scheduleBroadcastsLocked();
11361 return;
11362 }
11363
11364 r.state = BroadcastRecord.APP_RECEIVE;
11365 String targetProcess = info.activityInfo.processName;
11366 r.curComponent = new ComponentName(
11367 info.activityInfo.applicationInfo.packageName,
11368 info.activityInfo.name);
11369 r.curReceiver = info.activityInfo;
11370
11371 // Is this receiver's application already running?
11372 ProcessRecord app = getProcessRecordLocked(targetProcess,
11373 info.activityInfo.applicationInfo.uid);
11374 if (app != null && app.thread != null) {
11375 try {
11376 processCurBroadcastLocked(r, app);
11377 return;
11378 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011379 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011380 + r.curComponent, e);
11381 }
11382
11383 // If a dead object exception was thrown -- fall through to
11384 // restart the application.
11385 }
11386
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011387 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011388 if (DEBUG_BROADCAST) Slog.v(TAG,
11389 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011390 if ((r.curApp=startProcessLocked(targetProcess,
11391 info.activityInfo.applicationInfo, true,
11392 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011393 "broadcast", r.curComponent,
11394 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11395 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011396 // Ah, this recipient is unavailable. Finish it if necessary,
11397 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011398 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011399 + info.activityInfo.applicationInfo.packageName + "/"
11400 + info.activityInfo.applicationInfo.uid + " for broadcast "
11401 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011402 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011403 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11404 r.resultExtras, r.resultAbort, true);
11405 scheduleBroadcastsLocked();
11406 r.state = BroadcastRecord.IDLE;
11407 return;
11408 }
11409
11410 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011411 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011412 }
11413 }
11414
11415 // =========================================================
11416 // INSTRUMENTATION
11417 // =========================================================
11418
11419 public boolean startInstrumentation(ComponentName className,
11420 String profileFile, int flags, Bundle arguments,
11421 IInstrumentationWatcher watcher) {
11422 // Refuse possible leaked file descriptors
11423 if (arguments != null && arguments.hasFileDescriptors()) {
11424 throw new IllegalArgumentException("File descriptors passed in Bundle");
11425 }
11426
11427 synchronized(this) {
11428 InstrumentationInfo ii = null;
11429 ApplicationInfo ai = null;
11430 try {
11431 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011432 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011433 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011434 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011435 } catch (PackageManager.NameNotFoundException e) {
11436 }
11437 if (ii == null) {
11438 reportStartInstrumentationFailure(watcher, className,
11439 "Unable to find instrumentation info for: " + className);
11440 return false;
11441 }
11442 if (ai == null) {
11443 reportStartInstrumentationFailure(watcher, className,
11444 "Unable to find instrumentation target package: " + ii.targetPackage);
11445 return false;
11446 }
11447
11448 int match = mContext.getPackageManager().checkSignatures(
11449 ii.targetPackage, ii.packageName);
11450 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11451 String msg = "Permission Denial: starting instrumentation "
11452 + className + " from pid="
11453 + Binder.getCallingPid()
11454 + ", uid=" + Binder.getCallingPid()
11455 + " not allowed because package " + ii.packageName
11456 + " does not have a signature matching the target "
11457 + ii.targetPackage;
11458 reportStartInstrumentationFailure(watcher, className, msg);
11459 throw new SecurityException(msg);
11460 }
11461
11462 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011463 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011464 ProcessRecord app = addAppLocked(ai);
11465 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011466 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467 app.instrumentationProfileFile = profileFile;
11468 app.instrumentationArguments = arguments;
11469 app.instrumentationWatcher = watcher;
11470 app.instrumentationResultClass = className;
11471 Binder.restoreCallingIdentity(origId);
11472 }
11473
11474 return true;
11475 }
11476
11477 /**
11478 * Report errors that occur while attempting to start Instrumentation. Always writes the
11479 * error to the logs, but if somebody is watching, send the report there too. This enables
11480 * the "am" command to report errors with more information.
11481 *
11482 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11483 * @param cn The component name of the instrumentation.
11484 * @param report The error report.
11485 */
11486 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11487 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011488 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011489 try {
11490 if (watcher != null) {
11491 Bundle results = new Bundle();
11492 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11493 results.putString("Error", report);
11494 watcher.instrumentationStatus(cn, -1, results);
11495 }
11496 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011497 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011498 }
11499 }
11500
11501 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11502 if (app.instrumentationWatcher != null) {
11503 try {
11504 // NOTE: IInstrumentationWatcher *must* be oneway here
11505 app.instrumentationWatcher.instrumentationFinished(
11506 app.instrumentationClass,
11507 resultCode,
11508 results);
11509 } catch (RemoteException e) {
11510 }
11511 }
11512 app.instrumentationWatcher = null;
11513 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011514 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011515 app.instrumentationProfileFile = null;
11516 app.instrumentationArguments = null;
11517
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011518 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011519 }
11520
11521 public void finishInstrumentation(IApplicationThread target,
11522 int resultCode, Bundle results) {
11523 // Refuse possible leaked file descriptors
11524 if (results != null && results.hasFileDescriptors()) {
11525 throw new IllegalArgumentException("File descriptors passed in Intent");
11526 }
11527
11528 synchronized(this) {
11529 ProcessRecord app = getRecordForAppLocked(target);
11530 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011531 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011532 return;
11533 }
11534 final long origId = Binder.clearCallingIdentity();
11535 finishInstrumentationLocked(app, resultCode, results);
11536 Binder.restoreCallingIdentity(origId);
11537 }
11538 }
11539
11540 // =========================================================
11541 // CONFIGURATION
11542 // =========================================================
11543
11544 public ConfigurationInfo getDeviceConfigurationInfo() {
11545 ConfigurationInfo config = new ConfigurationInfo();
11546 synchronized (this) {
11547 config.reqTouchScreen = mConfiguration.touchscreen;
11548 config.reqKeyboardType = mConfiguration.keyboard;
11549 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011550 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11551 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011552 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11553 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011554 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11555 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011556 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11557 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011558 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011559 }
11560 return config;
11561 }
11562
11563 public Configuration getConfiguration() {
11564 Configuration ci;
11565 synchronized(this) {
11566 ci = new Configuration(mConfiguration);
11567 }
11568 return ci;
11569 }
11570
11571 public void updateConfiguration(Configuration values) {
11572 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11573 "updateConfiguration()");
11574
11575 synchronized(this) {
11576 if (values == null && mWindowManager != null) {
11577 // sentinel: fetch the current configuration from the window manager
11578 values = mWindowManager.computeNewConfiguration();
11579 }
11580
11581 final long origId = Binder.clearCallingIdentity();
11582 updateConfigurationLocked(values, null);
11583 Binder.restoreCallingIdentity(origId);
11584 }
11585 }
11586
11587 /**
11588 * Do either or both things: (1) change the current configuration, and (2)
11589 * make sure the given activity is running with the (now) current
11590 * configuration. Returns true if the activity has been left running, or
11591 * false if <var>starting</var> is being destroyed to match the new
11592 * configuration.
11593 */
11594 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011595 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011596 int changes = 0;
11597
11598 boolean kept = true;
11599
11600 if (values != null) {
11601 Configuration newConfig = new Configuration(mConfiguration);
11602 changes = newConfig.updateFrom(values);
11603 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011604 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011605 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011606 }
11607
Doug Zongker2bec3d42009-12-04 12:52:44 -080011608 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011609
11610 if (values.locale != null) {
11611 saveLocaleLocked(values.locale,
11612 !values.locale.equals(mConfiguration.locale),
11613 values.userSetLocale);
11614 }
11615
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011616 mConfigurationSeq++;
11617 if (mConfigurationSeq <= 0) {
11618 mConfigurationSeq = 1;
11619 }
11620 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011622 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011623
11624 AttributeCache ac = AttributeCache.instance();
11625 if (ac != null) {
11626 ac.updateConfiguration(mConfiguration);
11627 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011629 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11630 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11631 msg.obj = new Configuration(mConfiguration);
11632 mHandler.sendMessage(msg);
11633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011634
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011635 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11636 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011637 try {
11638 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011639 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011640 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011641 app.thread.scheduleConfigurationChanged(mConfiguration);
11642 }
11643 } catch (Exception e) {
11644 }
11645 }
11646 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011647 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11648 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011649 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11650 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011651 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11652 broadcastIntentLocked(null, null,
11653 new Intent(Intent.ACTION_LOCALE_CHANGED),
11654 null, null, 0, null, null,
11655 null, false, false, MY_PID, Process.SYSTEM_UID);
11656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011657 }
11658 }
11659
11660 if (changes != 0 && starting == null) {
11661 // If the configuration changed, and the caller is not already
11662 // in the process of starting an activity, then find the top
11663 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011664 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011665 }
11666
11667 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011668 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011669 if (kept) {
11670 // If this didn't result in the starting activity being
11671 // destroyed, then we need to make sure at this point that all
11672 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011673 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011674 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011675 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011676 }
11677 }
11678
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011679 if (values != null && mWindowManager != null) {
11680 mWindowManager.setNewConfiguration(mConfiguration);
11681 }
11682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011683 return kept;
11684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011685
11686 /**
11687 * Save the locale. You must be inside a synchronized (this) block.
11688 */
11689 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11690 if(isDiff) {
11691 SystemProperties.set("user.language", l.getLanguage());
11692 SystemProperties.set("user.region", l.getCountry());
11693 }
11694
11695 if(isPersist) {
11696 SystemProperties.set("persist.sys.language", l.getLanguage());
11697 SystemProperties.set("persist.sys.country", l.getCountry());
11698 SystemProperties.set("persist.sys.localevar", l.getVariant());
11699 }
11700 }
11701
11702 // =========================================================
11703 // LIFETIME MANAGEMENT
11704 // =========================================================
11705
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011706 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11707 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011708 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011709 // This adjustment has already been computed. If we are calling
11710 // from the top, we may have already computed our adjustment with
11711 // an earlier hidden adjustment that isn't really for us... if
11712 // so, use the new hidden adjustment.
11713 if (!recursed && app.hidden) {
11714 app.curAdj = hiddenAdj;
11715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011716 return app.curAdj;
11717 }
11718
11719 if (app.thread == null) {
11720 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011721 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011722 return (app.curAdj=EMPTY_APP_ADJ);
11723 }
11724
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011725 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11726 // The max adjustment doesn't allow this app to be anything
11727 // below foreground, so it is not worth doing work for it.
11728 app.adjType = "fixed";
11729 app.adjSeq = mAdjSeq;
11730 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011731 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011732 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11733 return (app.curAdj=app.maxAdj);
11734 }
11735
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011736 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011737 app.adjSource = null;
11738 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011739 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011740 app.empty = false;
11741 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011742
The Android Open Source Project4df24232009-03-05 14:34:35 -080011743 // Determine the importance of the process, starting with most
11744 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011745 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011746 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011747 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011748 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011749 // The last app on the list is the foreground app.
11750 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011751 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011752 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011753 } else if (app.instrumentationClass != null) {
11754 // Don't want to kill running instrumentation.
11755 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011756 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011757 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011758 } else if (app.curReceiver != null ||
11759 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11760 // An app that is currently receiving a broadcast also
11761 // counts as being in the foreground.
11762 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011763 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011764 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011765 } else if (app.executingServices.size() > 0) {
11766 // An app that is currently executing a service callback also
11767 // counts as being in the foreground.
11768 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011769 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011770 app.adjType = "exec-service";
11771 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011772 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011773 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011774 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011775 app.adjType = "foreground-service";
11776 } else if (app.forcingToForeground != null) {
11777 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011778 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011779 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011780 app.adjType = "force-foreground";
11781 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011782 } else if (app == mHeavyWeightProcess) {
11783 // We don't want to kill the current heavy-weight process.
11784 adj = HEAVY_WEIGHT_APP_ADJ;
11785 schedGroup = Process.THREAD_GROUP_DEFAULT;
11786 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011787 } else if (app == mHomeProcess) {
11788 // This process is hosting what we currently consider to be the
11789 // home app, so we don't want to let it go into the background.
11790 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011791 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011792 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011793 } else if ((N=app.activities.size()) != 0) {
11794 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011795 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011796 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011797 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011798 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011799 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011800 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011801 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011802 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011803 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011805 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011806 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011807 break;
11808 }
11809 }
11810 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011811 // A very not-needed process. If this is lower in the lru list,
11812 // we will push it in to the empty bucket.
11813 app.hidden = true;
11814 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011815 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011816 adj = hiddenAdj;
11817 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011818 }
11819
Joe Onorato8a9b2202010-02-26 18:56:32 -080011820 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011821
The Android Open Source Project4df24232009-03-05 14:34:35 -080011822 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011823 // there are applications dependent on our services or providers, but
11824 // this gives us a baseline and makes sure we don't get into an
11825 // infinite recursion.
11826 app.adjSeq = mAdjSeq;
11827 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011828
Christopher Tate6fa95972009-06-05 18:43:55 -070011829 if (mBackupTarget != null && app == mBackupTarget.app) {
11830 // If possible we want to avoid killing apps while they're being backed up
11831 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011832 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011833 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011834 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011835 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011836 }
11837 }
11838
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011839 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11840 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011841 final long now = SystemClock.uptimeMillis();
11842 // This process is more important if the top activity is
11843 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011844 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011845 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011846 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011847 if (s.startRequested) {
11848 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11849 // This service has seen some activity within
11850 // recent memory, so we will keep its process ahead
11851 // of the background processes.
11852 if (adj > SECONDARY_SERVER_ADJ) {
11853 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011854 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011855 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011856 }
11857 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011858 // If we have let the service slide into the background
11859 // state, still have some text describing what it is doing
11860 // even though the service no longer has an impact.
11861 if (adj > SECONDARY_SERVER_ADJ) {
11862 app.adjType = "started-bg-services";
11863 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011864 // Don't kill this process because it is doing work; it
11865 // has said it is doing work.
11866 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011867 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011868 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11869 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011870 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011871 = s.connections.values().iterator();
11872 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011873 ArrayList<ConnectionRecord> clist = kt.next();
11874 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11875 // XXX should compute this based on the max of
11876 // all connected clients.
11877 ConnectionRecord cr = clist.get(i);
11878 if (cr.binding.client == app) {
11879 // Binding to ourself is not interesting.
11880 continue;
11881 }
11882 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11883 ProcessRecord client = cr.binding.client;
11884 int myHiddenAdj = hiddenAdj;
11885 if (myHiddenAdj > client.hiddenAdj) {
11886 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11887 myHiddenAdj = client.hiddenAdj;
11888 } else {
11889 myHiddenAdj = VISIBLE_APP_ADJ;
11890 }
11891 }
11892 int clientAdj = computeOomAdjLocked(
11893 client, myHiddenAdj, TOP_APP, true);
11894 if (adj > clientAdj) {
11895 adj = clientAdj >= VISIBLE_APP_ADJ
11896 ? clientAdj : VISIBLE_APP_ADJ;
11897 if (!client.hidden) {
11898 app.hidden = false;
11899 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011900 if (client.keeping) {
11901 app.keeping = true;
11902 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011903 app.adjType = "service";
11904 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11905 .REASON_SERVICE_IN_USE;
11906 app.adjSource = cr.binding.client;
11907 app.adjTarget = s.name;
11908 }
11909 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11910 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11911 schedGroup = Process.THREAD_GROUP_DEFAULT;
11912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011913 }
11914 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011915 ActivityRecord a = cr.activity;
11916 //if (a != null) {
11917 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11918 //}
11919 if (a != null && adj > FOREGROUND_APP_ADJ &&
11920 (a.state == ActivityState.RESUMED
11921 || a.state == ActivityState.PAUSING)) {
11922 adj = FOREGROUND_APP_ADJ;
11923 schedGroup = Process.THREAD_GROUP_DEFAULT;
11924 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011925 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011926 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11927 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011928 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011929 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011930 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011931 }
11932 }
11933 }
11934 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011935
Dianne Hackborn287952c2010-09-22 22:34:31 -070011936 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011937 // would like to avoid killing it unless it would prevent the current
11938 // application from running. By default we put the process in
11939 // with the rest of the background processes; as we scan through
11940 // its services we may bump it up from there.
11941 if (adj > hiddenAdj) {
11942 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011943 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011944 app.adjType = "bg-services";
11945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011946 }
11947
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011948 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11949 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011950 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011951 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11952 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011953 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011954 if (cpr.clients.size() != 0) {
11955 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11956 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11957 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011958 if (client == app) {
11959 // Being our own client is not interesting.
11960 continue;
11961 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011962 int myHiddenAdj = hiddenAdj;
11963 if (myHiddenAdj > client.hiddenAdj) {
11964 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11965 myHiddenAdj = client.hiddenAdj;
11966 } else {
11967 myHiddenAdj = FOREGROUND_APP_ADJ;
11968 }
11969 }
11970 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011971 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011972 if (adj > clientAdj) {
11973 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011974 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011975 if (!client.hidden) {
11976 app.hidden = false;
11977 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011978 if (client.keeping) {
11979 app.keeping = true;
11980 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011981 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011982 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11983 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011984 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011985 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011986 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011987 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11988 schedGroup = Process.THREAD_GROUP_DEFAULT;
11989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011990 }
11991 }
11992 // If the provider has external (non-framework) process
11993 // dependencies, ensure that its adjustment is at least
11994 // FOREGROUND_APP_ADJ.
11995 if (cpr.externals != 0) {
11996 if (adj > FOREGROUND_APP_ADJ) {
11997 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011998 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011999 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012000 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012001 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012002 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012003 }
12004 }
12005 }
12006 }
12007
12008 app.curRawAdj = adj;
12009
Joe Onorato8a9b2202010-02-26 18:56:32 -080012010 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012011 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12012 if (adj > app.maxAdj) {
12013 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012014 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012015 schedGroup = Process.THREAD_GROUP_DEFAULT;
12016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012018 if (adj < HIDDEN_APP_MIN_ADJ) {
12019 app.keeping = true;
12020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012021
12022 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012023 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012025 return adj;
12026 }
12027
12028 /**
12029 * Ask a given process to GC right now.
12030 */
12031 final void performAppGcLocked(ProcessRecord app) {
12032 try {
12033 app.lastRequestedGc = SystemClock.uptimeMillis();
12034 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012035 if (app.reportLowMemory) {
12036 app.reportLowMemory = false;
12037 app.thread.scheduleLowMemory();
12038 } else {
12039 app.thread.processInBackground();
12040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012041 }
12042 } catch (Exception e) {
12043 // whatever.
12044 }
12045 }
12046
12047 /**
12048 * Returns true if things are idle enough to perform GCs.
12049 */
Josh Bartel7f208742010-02-25 11:01:44 -060012050 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012051 return mParallelBroadcasts.size() == 0
12052 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012053 && (mSleeping || (mMainStack.mResumedActivity != null &&
12054 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012055 }
12056
12057 /**
12058 * Perform GCs on all processes that are waiting for it, but only
12059 * if things are idle.
12060 */
12061 final void performAppGcsLocked() {
12062 final int N = mProcessesToGc.size();
12063 if (N <= 0) {
12064 return;
12065 }
Josh Bartel7f208742010-02-25 11:01:44 -060012066 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012067 while (mProcessesToGc.size() > 0) {
12068 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012069 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012070 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12071 <= SystemClock.uptimeMillis()) {
12072 // To avoid spamming the system, we will GC processes one
12073 // at a time, waiting a few seconds between each.
12074 performAppGcLocked(proc);
12075 scheduleAppGcsLocked();
12076 return;
12077 } else {
12078 // It hasn't been long enough since we last GCed this
12079 // process... put it in the list to wait for its time.
12080 addProcessToGcListLocked(proc);
12081 break;
12082 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012083 }
12084 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012085
12086 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012087 }
12088 }
12089
12090 /**
12091 * If all looks good, perform GCs on all processes waiting for them.
12092 */
12093 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012094 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012095 performAppGcsLocked();
12096 return;
12097 }
12098 // Still not idle, wait some more.
12099 scheduleAppGcsLocked();
12100 }
12101
12102 /**
12103 * Schedule the execution of all pending app GCs.
12104 */
12105 final void scheduleAppGcsLocked() {
12106 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012107
12108 if (mProcessesToGc.size() > 0) {
12109 // Schedule a GC for the time to the next process.
12110 ProcessRecord proc = mProcessesToGc.get(0);
12111 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12112
12113 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12114 long now = SystemClock.uptimeMillis();
12115 if (when < (now+GC_TIMEOUT)) {
12116 when = now + GC_TIMEOUT;
12117 }
12118 mHandler.sendMessageAtTime(msg, when);
12119 }
12120 }
12121
12122 /**
12123 * Add a process to the array of processes waiting to be GCed. Keeps the
12124 * list in sorted order by the last GC time. The process can't already be
12125 * on the list.
12126 */
12127 final void addProcessToGcListLocked(ProcessRecord proc) {
12128 boolean added = false;
12129 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12130 if (mProcessesToGc.get(i).lastRequestedGc <
12131 proc.lastRequestedGc) {
12132 added = true;
12133 mProcessesToGc.add(i+1, proc);
12134 break;
12135 }
12136 }
12137 if (!added) {
12138 mProcessesToGc.add(0, proc);
12139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012140 }
12141
12142 /**
12143 * Set up to ask a process to GC itself. This will either do it
12144 * immediately, or put it on the list of processes to gc the next
12145 * time things are idle.
12146 */
12147 final void scheduleAppGcLocked(ProcessRecord app) {
12148 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012149 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012150 return;
12151 }
12152 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012153 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012154 scheduleAppGcsLocked();
12155 }
12156 }
12157
Dianne Hackborn287952c2010-09-22 22:34:31 -070012158 final void checkExcessivePowerUsageLocked(boolean doKills) {
12159 updateCpuStatsNow();
12160
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012161 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012162 boolean doWakeKills = doKills;
12163 boolean doCpuKills = doKills;
12164 if (mLastPowerCheckRealtime == 0) {
12165 doWakeKills = false;
12166 }
12167 if (mLastPowerCheckUptime == 0) {
12168 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012169 }
12170 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012171 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012172 }
12173 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012174 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12175 final long curUptime = SystemClock.uptimeMillis();
12176 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12177 mLastPowerCheckRealtime = curRealtime;
12178 mLastPowerCheckUptime = curUptime;
12179 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12180 doWakeKills = false;
12181 }
12182 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12183 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012184 }
12185 int i = mLruProcesses.size();
12186 while (i > 0) {
12187 i--;
12188 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012189 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012190 long wtime;
12191 synchronized (stats) {
12192 wtime = stats.getProcessWakeTime(app.info.uid,
12193 app.pid, curRealtime);
12194 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012195 long wtimeUsed = wtime - app.lastWakeTime;
12196 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12197 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012198 StringBuilder sb = new StringBuilder(128);
12199 sb.append("Wake for ");
12200 app.toShortString(sb);
12201 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012202 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012203 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012204 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012205 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012206 sb.append((wtimeUsed*100)/realtimeSince);
12207 sb.append("%)");
12208 Slog.i(TAG, sb.toString());
12209 sb.setLength(0);
12210 sb.append("CPU for ");
12211 app.toShortString(sb);
12212 sb.append(": over ");
12213 TimeUtils.formatDuration(uptimeSince, sb);
12214 sb.append(" used ");
12215 TimeUtils.formatDuration(cputimeUsed, sb);
12216 sb.append(" (");
12217 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012218 sb.append("%)");
12219 Slog.i(TAG, sb.toString());
12220 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012221 // If a process has held a wake lock for more
12222 // than 50% of the time during this period,
12223 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012224 if (doWakeKills && realtimeSince > 0
12225 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12226 synchronized (stats) {
12227 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12228 realtimeSince, wtimeUsed);
12229 }
12230 Slog.w(TAG, "Excessive wake lock in " + app.processName
12231 + " (pid " + app.pid + "): held " + wtimeUsed
12232 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012233 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12234 app.processName, app.setAdj, "excessive wake lock");
12235 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012236 } else if (doCpuKills && uptimeSince > 0
12237 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12238 synchronized (stats) {
12239 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12240 uptimeSince, cputimeUsed);
12241 }
12242 Slog.w(TAG, "Excessive CPU in " + app.processName
12243 + " (pid " + app.pid + "): used " + cputimeUsed
12244 + " during " + uptimeSince);
12245 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12246 app.processName, app.setAdj, "excessive cpu");
12247 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012248 } else {
12249 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012250 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012251 }
12252 }
12253 }
12254 }
12255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012256 private final boolean updateOomAdjLocked(
12257 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12258 app.hiddenAdj = hiddenAdj;
12259
12260 if (app.thread == null) {
12261 return true;
12262 }
12263
Dianne Hackborn287952c2010-09-22 22:34:31 -070012264 final boolean wasKeeping = app.keeping;
12265
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012266 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012267
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012268 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012269 if (app.curRawAdj != app.setRawAdj) {
12270 if (app.curRawAdj > FOREGROUND_APP_ADJ
12271 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12272 // If this app is transitioning from foreground to
12273 // non-foreground, have it do a gc.
12274 scheduleAppGcLocked(app);
12275 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12276 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12277 // Likewise do a gc when an app is moving in to the
12278 // background (such as a service stopping).
12279 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012280 }
12281
12282 if (wasKeeping && !app.keeping) {
12283 // This app is no longer something we want to keep. Note
12284 // its current wake lock time to later know to kill it if
12285 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012286 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12287 synchronized (stats) {
12288 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12289 app.pid, SystemClock.elapsedRealtime());
12290 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012291 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012292 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012294 app.setRawAdj = app.curRawAdj;
12295 }
12296 if (adj != app.setAdj) {
12297 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012298 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012299 TAG, "Set app " + app.processName +
12300 " oom adj to " + adj);
12301 app.setAdj = adj;
12302 } else {
12303 return false;
12304 }
12305 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012306 if (app.setSchedGroup != app.curSchedGroup) {
12307 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012308 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012309 "Setting process group of " + app.processName
12310 + " to " + app.curSchedGroup);
12311 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012312 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012313 try {
12314 Process.setProcessGroup(app.pid, app.curSchedGroup);
12315 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012316 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012317 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012318 e.printStackTrace();
12319 } finally {
12320 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012321 }
12322 }
12323 if (false) {
12324 if (app.thread != null) {
12325 try {
12326 app.thread.setSchedulingGroup(app.curSchedGroup);
12327 } catch (RemoteException e) {
12328 }
12329 }
12330 }
12331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012332 }
12333
12334 return true;
12335 }
12336
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012337 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012338 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012339 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012340 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012341 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012342 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012343 }
12344 }
12345 return resumedActivity;
12346 }
12347
12348 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012349 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012350 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12351 int curAdj = app.curAdj;
12352 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12353 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12354
12355 mAdjSeq++;
12356
12357 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12358 if (res) {
12359 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12360 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12361 if (nowHidden != wasHidden) {
12362 // Changed to/from hidden state, so apps after it in the LRU
12363 // list may also be changed.
12364 updateOomAdjLocked();
12365 }
12366 }
12367 return res;
12368 }
12369
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012370 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012371 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012372 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012373 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12374
12375 if (false) {
12376 RuntimeException e = new RuntimeException();
12377 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012378 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012379 }
12380
12381 mAdjSeq++;
12382
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012383 // Let's determine how many processes we have running vs.
12384 // how many slots we have for background processes; we may want
12385 // to put multiple processes in a slot of there are enough of
12386 // them.
12387 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12388 int factor = (mLruProcesses.size()-4)/numSlots;
12389 if (factor < 1) factor = 1;
12390 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012391 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012393 // First try updating the OOM adjustment for each of the
12394 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012395 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012396 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12397 while (i > 0) {
12398 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012399 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012400 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012401 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012402 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012403 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012404 step++;
12405 if (step >= factor) {
12406 step = 0;
12407 curHiddenAdj++;
12408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012409 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012410 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012411 if (!app.killedBackground) {
12412 numHidden++;
12413 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012414 Slog.i(TAG, "No longer want " + app.processName
12415 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012416 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12417 app.processName, app.setAdj, "too many background");
12418 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012419 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012420 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012421 }
12422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012423 } else {
12424 didOomAdj = false;
12425 }
12426 }
12427
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012428 // If we return false, we will fall back on killing processes to
12429 // have a fixed limit. Do this if a limit has been requested; else
12430 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012431 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12432 }
12433
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012434 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012435 synchronized (this) {
12436 int i;
12437
12438 // First remove any unused application processes whose package
12439 // has been removed.
12440 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12441 final ProcessRecord app = mRemovedProcesses.get(i);
12442 if (app.activities.size() == 0
12443 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012444 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012445 TAG, "Exiting empty application process "
12446 + app.processName + " ("
12447 + (app.thread != null ? app.thread.asBinder() : null)
12448 + ")\n");
12449 if (app.pid > 0 && app.pid != MY_PID) {
12450 Process.killProcess(app.pid);
12451 } else {
12452 try {
12453 app.thread.scheduleExit();
12454 } catch (Exception e) {
12455 // Ignore exceptions.
12456 }
12457 }
12458 cleanUpApplicationRecordLocked(app, false, -1);
12459 mRemovedProcesses.remove(i);
12460
12461 if (app.persistent) {
12462 if (app.persistent) {
12463 addAppLocked(app.info);
12464 }
12465 }
12466 }
12467 }
12468
12469 // Now try updating the OOM adjustment for each of the
12470 // application processes based on their current state.
12471 // If the setOomAdj() API is not supported, then go with our
12472 // back-up plan...
12473 if (!updateOomAdjLocked()) {
12474
12475 // Count how many processes are running services.
12476 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012477 for (i=mLruProcesses.size()-1; i>=0; i--) {
12478 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012479
12480 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012481 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012482 // Don't count processes holding services against our
12483 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012484 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012485 TAG, "Not trimming app " + app + " with services: "
12486 + app.services);
12487 numServiceProcs++;
12488 }
12489 }
12490
12491 int curMaxProcs = mProcessLimit;
12492 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12493 if (mAlwaysFinishActivities) {
12494 curMaxProcs = 1;
12495 }
12496 curMaxProcs += numServiceProcs;
12497
12498 // Quit as many processes as we can to get down to the desired
12499 // process count. First remove any processes that no longer
12500 // have activites running in them.
12501 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012502 i<mLruProcesses.size()
12503 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012504 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012505 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012506 // Quit an application only if it is not currently
12507 // running any activities.
12508 if (!app.persistent && app.activities.size() == 0
12509 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012510 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012511 TAG, "Exiting empty application process "
12512 + app.processName + " ("
12513 + (app.thread != null ? app.thread.asBinder() : null)
12514 + ")\n");
12515 if (app.pid > 0 && app.pid != MY_PID) {
12516 Process.killProcess(app.pid);
12517 } else {
12518 try {
12519 app.thread.scheduleExit();
12520 } catch (Exception e) {
12521 // Ignore exceptions.
12522 }
12523 }
12524 // todo: For now we assume the application is not buggy
12525 // or evil, and will quit as a result of our request.
12526 // Eventually we need to drive this off of the death
12527 // notification, and kill the process if it takes too long.
12528 cleanUpApplicationRecordLocked(app, false, i);
12529 i--;
12530 }
12531 }
12532
12533 // If we still have too many processes, now from the least
12534 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012535 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012536 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012537 " of " + curMaxProcs + " processes");
12538 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012539 i<mLruProcesses.size()
12540 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012541 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012542 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012543 // Quit the application only if we have a state saved for
12544 // all of its activities.
12545 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012546 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012547 int NUMA = app.activities.size();
12548 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012549 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012550 TAG, "Looking to quit " + app.processName);
12551 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012552 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012553 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012554 TAG, " " + r.intent.getComponent().flattenToShortString()
12555 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12556 canQuit = (r.haveState || !r.stateNotNeeded)
12557 && !r.visible && r.stopped;
12558 }
12559 if (canQuit) {
12560 // Finish all of the activities, and then the app itself.
12561 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012562 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012563 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012564 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012565 }
12566 r.resultTo = null;
12567 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012568 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012569 + app.processName + " ("
12570 + (app.thread != null ? app.thread.asBinder() : null)
12571 + ")\n");
12572 if (app.pid > 0 && app.pid != MY_PID) {
12573 Process.killProcess(app.pid);
12574 } else {
12575 try {
12576 app.thread.scheduleExit();
12577 } catch (Exception e) {
12578 // Ignore exceptions.
12579 }
12580 }
12581 // todo: For now we assume the application is not buggy
12582 // or evil, and will quit as a result of our request.
12583 // Eventually we need to drive this off of the death
12584 // notification, and kill the process if it takes too long.
12585 cleanUpApplicationRecordLocked(app, false, i);
12586 i--;
12587 //dump();
12588 }
12589 }
12590
12591 }
12592
12593 int curMaxActivities = MAX_ACTIVITIES;
12594 if (mAlwaysFinishActivities) {
12595 curMaxActivities = 1;
12596 }
12597
12598 // Finally, if there are too many activities now running, try to
12599 // finish as many as we can to get back down to the limit.
12600 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012601 i<mMainStack.mLRUActivities.size()
12602 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012603 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012604 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012605 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012606
12607 // We can finish this one if we have its icicle saved and
12608 // it is not persistent.
12609 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012610 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012611 final int origSize = mMainStack.mLRUActivities.size();
12612 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012613
12614 // This will remove it from the LRU list, so keep
12615 // our index at the same value. Note that this check to
12616 // see if the size changes is just paranoia -- if
12617 // something unexpected happens, we don't want to end up
12618 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012619 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012620 i--;
12621 }
12622 }
12623 }
12624 }
12625 }
12626
12627 /** This method sends the specified signal to each of the persistent apps */
12628 public void signalPersistentProcesses(int sig) throws RemoteException {
12629 if (sig != Process.SIGNAL_USR1) {
12630 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12631 }
12632
12633 synchronized (this) {
12634 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12635 != PackageManager.PERMISSION_GRANTED) {
12636 throw new SecurityException("Requires permission "
12637 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12638 }
12639
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012640 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12641 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012642 if (r.thread != null && r.persistent) {
12643 Process.sendSignal(r.pid, sig);
12644 }
12645 }
12646 }
12647 }
12648
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012649 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012650 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012651
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012652 try {
12653 synchronized (this) {
12654 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12655 // its own permission.
12656 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12657 != PackageManager.PERMISSION_GRANTED) {
12658 throw new SecurityException("Requires permission "
12659 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012660 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012661
12662 if (start && fd == null) {
12663 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012664 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012665
12666 ProcessRecord proc = null;
12667 try {
12668 int pid = Integer.parseInt(process);
12669 synchronized (mPidsSelfLocked) {
12670 proc = mPidsSelfLocked.get(pid);
12671 }
12672 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012673 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012674
12675 if (proc == null) {
12676 HashMap<String, SparseArray<ProcessRecord>> all
12677 = mProcessNames.getMap();
12678 SparseArray<ProcessRecord> procs = all.get(process);
12679 if (procs != null && procs.size() > 0) {
12680 proc = procs.valueAt(0);
12681 }
12682 }
12683
12684 if (proc == null || proc.thread == null) {
12685 throw new IllegalArgumentException("Unknown process: " + process);
12686 }
12687
12688 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12689 if (isSecure) {
12690 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12691 throw new SecurityException("Process not debuggable: " + proc);
12692 }
12693 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012694
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012695 proc.thread.profilerControl(start, path, fd);
12696 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012697 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012698 }
12699 } catch (RemoteException e) {
12700 throw new IllegalStateException("Process disappeared");
12701 } finally {
12702 if (fd != null) {
12703 try {
12704 fd.close();
12705 } catch (IOException e) {
12706 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012707 }
12708 }
12709 }
Andy McFadden824c5102010-07-09 16:26:57 -070012710
12711 public boolean dumpHeap(String process, boolean managed,
12712 String path, ParcelFileDescriptor fd) throws RemoteException {
12713
12714 try {
12715 synchronized (this) {
12716 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12717 // its own permission (same as profileControl).
12718 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12719 != PackageManager.PERMISSION_GRANTED) {
12720 throw new SecurityException("Requires permission "
12721 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12722 }
12723
12724 if (fd == null) {
12725 throw new IllegalArgumentException("null fd");
12726 }
12727
12728 ProcessRecord proc = null;
12729 try {
12730 int pid = Integer.parseInt(process);
12731 synchronized (mPidsSelfLocked) {
12732 proc = mPidsSelfLocked.get(pid);
12733 }
12734 } catch (NumberFormatException e) {
12735 }
12736
12737 if (proc == null) {
12738 HashMap<String, SparseArray<ProcessRecord>> all
12739 = mProcessNames.getMap();
12740 SparseArray<ProcessRecord> procs = all.get(process);
12741 if (procs != null && procs.size() > 0) {
12742 proc = procs.valueAt(0);
12743 }
12744 }
12745
12746 if (proc == null || proc.thread == null) {
12747 throw new IllegalArgumentException("Unknown process: " + process);
12748 }
12749
12750 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12751 if (isSecure) {
12752 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12753 throw new SecurityException("Process not debuggable: " + proc);
12754 }
12755 }
12756
12757 proc.thread.dumpHeap(managed, path, fd);
12758 fd = null;
12759 return true;
12760 }
12761 } catch (RemoteException e) {
12762 throw new IllegalStateException("Process disappeared");
12763 } finally {
12764 if (fd != null) {
12765 try {
12766 fd.close();
12767 } catch (IOException e) {
12768 }
12769 }
12770 }
12771 }
12772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012773 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12774 public void monitor() {
12775 synchronized (this) { }
12776 }
12777}