blob: b463e560aca45d232160b67d652c30fb74216990 [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;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070027import com.android.server.am.ActivityStack.ActivityState;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070028import com.android.server.net.NetworkPolicyManagerService;
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080029import com.android.server.wm.WindowManagerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
Dianne Hackborndd71fc82009-12-16 19:24:32 -080031import dalvik.system.Zygote;
32
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.app.Activity;
34import android.app.ActivityManager;
35import android.app.ActivityManagerNative;
36import android.app.ActivityThread;
37import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070038import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020039import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070041import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.app.IActivityWatcher;
43import android.app.IApplicationThread;
44import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070045import android.app.INotificationManager;
Jeff Sharkeya4620792011-05-20 15:29:23 -070046import android.app.IProcessObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.app.IServiceConnection;
48import android.app.IThumbnailReceiver;
Dianne Hackbornf26fd992011-04-08 18:14:09 -070049import android.app.IThumbnailRetriever;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070051import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070052import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070054import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080055import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020056import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080057import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.content.ComponentName;
59import android.content.ContentResolver;
60import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020061import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.content.Intent;
63import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070064import android.content.IIntentReceiver;
65import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070066import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.ActivityInfo;
68import android.content.pm.ApplicationInfo;
69import android.content.pm.ConfigurationInfo;
70import android.content.pm.IPackageDataObserver;
71import android.content.pm.IPackageManager;
72import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080073import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070075import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import android.content.pm.ProviderInfo;
77import android.content.pm.ResolveInfo;
78import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070079import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackborne2515ee2011-04-27 18:52:56 -040080import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.content.res.Configuration;
82import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070083import android.net.Proxy;
84import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.net.Uri;
86import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080087import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080088import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070089import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080090import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080092import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.os.FileUtils;
94import android.os.Handler;
95import android.os.IBinder;
Dianne Hackborne17aeb32011-04-07 15:11:57 -070096import android.os.IInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.IPermissionController;
98import android.os.Looper;
99import android.os.Message;
100import android.os.Parcel;
101import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700103import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.os.RemoteException;
105import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700106import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.os.SystemClock;
108import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800111import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800112import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113import android.util.PrintWriterPrinter;
114import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700115import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116import android.view.Gravity;
117import android.view.LayoutInflater;
118import android.view.View;
119import android.view.WindowManager;
120import android.view.WindowManagerPolicy;
121
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700122import java.io.BufferedInputStream;
123import java.io.BufferedOutputStream;
124import java.io.DataInputStream;
125import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126import java.io.File;
127import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700128import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700130import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200131import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800132import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133import java.io.PrintWriter;
134import java.lang.IllegalStateException;
135import java.lang.ref.WeakReference;
136import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700137import java.util.Collections;
138import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139import java.util.HashMap;
140import java.util.HashSet;
141import java.util.Iterator;
142import java.util.List;
143import java.util.Locale;
144import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700145import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700146import java.util.concurrent.atomic.AtomicBoolean;
147import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700149public final class ActivityManagerService extends ActivityManagerNative
150 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 static final String TAG = "ActivityManager";
152 static final boolean DEBUG = false;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400153 static final boolean localLOGV = DEBUG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final boolean DEBUG_SWITCH = localLOGV || false;
155 static final boolean DEBUG_TASKS = localLOGV || false;
156 static final boolean DEBUG_PAUSE = localLOGV || false;
157 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
158 static final boolean DEBUG_TRANSITION = localLOGV || false;
159 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700160 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700162 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 static final boolean DEBUG_VISBILITY = localLOGV || false;
164 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700165 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800166 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700168 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate4a627c72011-04-01 14:43:32 -0700169 static final boolean DEBUG_BACKUP = localLOGV || true;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700170 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700171 static final boolean DEBUG_POWER = localLOGV || false;
172 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 static final boolean VALIDATE_TOKENS = false;
174 static final boolean SHOW_ACTIVITY_START_TIME = true;
175
176 // Control over CPU and battery monitoring.
177 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
178 static final boolean MONITOR_CPU_USAGE = true;
179 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
180 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
181 static final boolean MONITOR_THREAD_CPU_USAGE = false;
182
Dianne Hackborn1655be42009-05-08 14:29:01 -0700183 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700184 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 private static final String SYSTEM_SECURE = "ro.secure";
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800187 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188
189 // This is the maximum number of application processes we would like
190 // to have running. Due to the asynchronous nature of things, we can
191 // temporarily go beyond this limit.
192 static final int MAX_PROCESSES = 2;
193
194 // Set to false to leave processes running indefinitely, relying on
195 // the kernel killing them as resources are required.
196 static final boolean ENFORCE_PROCESS_LIMIT = false;
197
198 // This is the maximum number of activities that we would like to have
199 // running at a given time.
200 static final int MAX_ACTIVITIES = 20;
201
202 // Maximum number of recent tasks that we can remember.
203 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700204
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700205 // Amount of time after a call to stopAppSwitches() during which we will
206 // prevent further untrusted switches from happening.
207 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208
209 // How long we wait for a launched process to attach to the activity manager
210 // before we decide it's never going to come up for real.
211 static final int PROC_START_TIMEOUT = 10*1000;
212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 // How long to wait after going idle before forcing apps to GC.
214 static final int GC_TIMEOUT = 5*1000;
215
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700216 // The minimum amount of time between successive GC requests for a process.
217 static final int GC_MIN_INTERVAL = 60*1000;
218
Dianne Hackborn287952c2010-09-22 22:34:31 -0700219 // The rate at which we check for apps using excessive power -- 15 mins.
220 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
221
222 // The minimum sample duration we will allow before deciding we have
223 // enough data on wake locks to start killing things.
224 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
225
226 // The minimum sample duration we will allow before deciding we have
227 // enough data on CPU usage to start killing things.
228 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 // How long we allow a receiver to run before giving up on it.
231 static final int BROADCAST_TIMEOUT = 10*1000;
232
233 // How long we wait for a service to finish executing.
234 static final int SERVICE_TIMEOUT = 20*1000;
235
236 // How long a service needs to be running until restarting its process
237 // is no longer considered to be a relaunch of the service.
238 static final int SERVICE_RESTART_DURATION = 5*1000;
239
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700240 // How long a service needs to be running until it will start back at
241 // SERVICE_RESTART_DURATION after being killed.
242 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
243
244 // Multiplying factor to increase restart duration time by, for each time
245 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
246 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
247
248 // The minimum amount of time between restarting services that we allow.
249 // That is, when multiple services are restarting, we won't allow each
250 // to restart less than this amount of time from the last one.
251 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 // Maximum amount of time for there to be no activity on a service before
254 // we consider it non-essential and allow its process to go on the
255 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700256 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257
258 // How long we wait until we timeout on key dispatching.
259 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
260
261 // The minimum time we allow between crashes, for us to consider this
262 // application to be bad and stop and its services and reject broadcasts.
263 static final int MIN_CRASH_INTERVAL = 60*1000;
264
265 // How long we wait until we timeout on key dispatching during instrumentation.
266 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
267
268 // OOM adjustments for processes in various states:
269
270 // This is a process without anything currently running in it. Definitely
271 // the first to go! Value set in system/rootdir/init.rc on startup.
272 // This value is initalized in the constructor, careful when refering to
273 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800274 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275
276 // This is a process only hosting activities that are not visible,
277 // so it can be killed without any disruption. Value set in
278 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800279 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 static int HIDDEN_APP_MIN_ADJ;
281
The Android Open Source Project4df24232009-03-05 14:34:35 -0800282 // This is a process holding the home application -- we want to try
283 // avoiding killing it, even if it would normally be in the background,
284 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800285 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800286
Christopher Tate6fa95972009-06-05 18:43:55 -0700287 // This is a process currently hosting a backup operation. Killing it
288 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 // This is a process holding a secondary server -- killing it will not
292 // have much of an impact as far as the user is concerned. Value set in
293 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800294 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700296 // This is a process with a heavy-weight application. It is in the
297 // background, but we want to try to avoid killing it. Value set in
298 // system/rootdir/init.rc on startup.
299 static final int HEAVY_WEIGHT_APP_ADJ;
300
301 // This is a process only hosting components that are perceptible to the
302 // user, and we really want to avoid killing them, but they are not
303 // immediately visible. An example is background music playback. Value set in
304 // system/rootdir/init.rc on startup.
305 static final int PERCEPTIBLE_APP_ADJ;
306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 // This is a process only hosting activities that are visible to the
308 // user, so we'd prefer they don't disappear. Value set in
309 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800310 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311
312 // This is the process running the current foreground app. We'd really
313 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800314 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315
316 // This is a process running a core server, such as telephony. Definitely
317 // don't want to kill it, but doing so is not completely fatal.
318 static final int CORE_SERVER_ADJ = -12;
319
320 // The system process runs at the default adjustment.
321 static final int SYSTEM_ADJ = -16;
322
323 // Memory pages are 4K.
324 static final int PAGE_SIZE = 4*1024;
325
326 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800327 static final int EMPTY_APP_MEM;
328 static final int HIDDEN_APP_MEM;
329 static final int HOME_APP_MEM;
330 static final int BACKUP_APP_MEM;
331 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700332 static final int HEAVY_WEIGHT_APP_MEM;
333 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800334 static final int VISIBLE_APP_MEM;
335 static final int FOREGROUND_APP_MEM;
336
337 // The minimum number of hidden apps we want to be able to keep around,
338 // without empty apps being able to push them out of memory.
339 static final int MIN_HIDDEN_APPS = 2;
340
Dianne Hackborn8633e682010-04-22 16:03:41 -0700341 // The maximum number of hidden processes we will keep around before
342 // killing them; this is just a control to not let us go too crazy with
343 // keeping around processes on devices with large amounts of RAM.
344 static final int MAX_HIDDEN_APPS = 15;
345
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800346 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700347 // been idle for less than 15 seconds.
348 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800349
350 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700351 // been idle for less than 120 seconds.
352 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800353
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700354 static int getIntProp(String name, boolean allowZero) {
355 String str = SystemProperties.get(name);
356 if (str == null) {
357 throw new IllegalArgumentException("Property not defined: " + name);
358 }
359 int val = Integer.valueOf(str);
360 if (val == 0 && !allowZero) {
361 throw new IllegalArgumentException("Property must not be zero: " + name);
362 }
363 return val;
364 }
365
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800366 static {
367 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700368 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
369 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
370 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
371 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
372 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
373 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
374 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
375 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
376 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
377 // These days we use the last empty slot for hidden apps as well.
378 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
379 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
380 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
381 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
382 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
383 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
384 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
385 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
386 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
387 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389
Dan Egnor42471dd2010-01-07 17:25:22 -0800390 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391
392 static final String[] EMPTY_STRING_ARRAY = new String[0];
393
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700394 public ActivityStack mMainStack;
395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700397 * Description of a request to start a new activity, which has been held
398 * due to app switches being disabled.
399 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700400 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700401 ActivityRecord r;
402 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700403 Uri[] grantedUriPermissions;
404 int grantedMode;
405 boolean onlyIfNeeded;
406 }
407
408 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
409 = new ArrayList<PendingActivityLaunch>();
410
411 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 * List of all active broadcasts that are to be executed immediately
413 * (without waiting for another broadcast to finish). Currently this only
414 * contains broadcasts to registered receivers, to avoid spinning up
415 * a bunch of processes to execute IntentReceiver components.
416 */
417 final ArrayList<BroadcastRecord> mParallelBroadcasts
418 = new ArrayList<BroadcastRecord>();
419
420 /**
421 * List of all active broadcasts that are to be executed one at a time.
422 * The object at the top of the list is the currently activity broadcasts;
423 * those after it are waiting for the top to finish..
424 */
425 final ArrayList<BroadcastRecord> mOrderedBroadcasts
426 = new ArrayList<BroadcastRecord>();
427
428 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800429 * Historical data of past broadcasts, for debugging.
430 */
431 static final int MAX_BROADCAST_HISTORY = 100;
432 final BroadcastRecord[] mBroadcastHistory
433 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
434
435 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 * Set when we current have a BROADCAST_INTENT_MSG in flight.
437 */
438 boolean mBroadcastsScheduled = false;
439
440 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 * Activity we have told the window manager to have key focus.
442 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700443 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700444 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 * List of intents that were used to start the most recent tasks.
446 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700447 final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448
449 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 * All of the applications we currently have running organized by name.
451 * The keys are strings of the application package name (as
452 * returned by the package manager), and the keys are ApplicationRecord
453 * objects.
454 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700455 final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456
457 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700458 * The currently running heavy-weight process, if any.
459 */
460 ProcessRecord mHeavyWeightProcess = null;
461
462 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 * The last time that various processes have crashed.
464 */
465 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
466
467 /**
468 * Set of applications that we consider to be bad, and will reject
469 * incoming broadcasts from (which the user has no control over).
470 * Processes are added to this set when they have crashed twice within
471 * a minimum amount of time; they are removed from it when they are
472 * later restarted (hopefully due to some user action). The value is the
473 * time it was added to the list.
474 */
475 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
476
477 /**
478 * All of the processes we currently have running organized by pid.
479 * The keys are the pid running the application.
480 *
481 * <p>NOTE: This object is protected by its own lock, NOT the global
482 * activity manager lock!
483 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700484 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485
486 /**
487 * All of the processes that have been forced to be foreground. The key
488 * is the pid of the caller who requested it (we hold a death
489 * link on it).
490 */
491 abstract class ForegroundToken implements IBinder.DeathRecipient {
492 int pid;
493 IBinder token;
494 }
495 final SparseArray<ForegroundToken> mForegroundProcesses
496 = new SparseArray<ForegroundToken>();
497
498 /**
499 * List of records for processes that someone had tried to start before the
500 * system was ready. We don't start them at that point, but ensure they
501 * are started by the time booting is complete.
502 */
503 final ArrayList<ProcessRecord> mProcessesOnHold
504 = new ArrayList<ProcessRecord>();
505
506 /**
507 * List of records for processes that we have started and are waiting
508 * for them to call back. This is really only needed when running in
509 * single processes mode, in which case we do not have a unique pid for
510 * each process.
511 */
512 final ArrayList<ProcessRecord> mStartingProcesses
513 = new ArrayList<ProcessRecord>();
514
515 /**
516 * List of persistent applications that are in the process
517 * of being started.
518 */
519 final ArrayList<ProcessRecord> mPersistentStartingProcesses
520 = new ArrayList<ProcessRecord>();
521
522 /**
523 * Processes that are being forcibly torn down.
524 */
525 final ArrayList<ProcessRecord> mRemovedProcesses
526 = new ArrayList<ProcessRecord>();
527
528 /**
529 * List of running applications, sorted by recent usage.
530 * The first entry in the list is the least recently used.
531 * It contains ApplicationRecord objects. This list does NOT include
532 * any persistent application records (since we never want to exit them).
533 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800534 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 = new ArrayList<ProcessRecord>();
536
537 /**
538 * List of processes that should gc as soon as things are idle.
539 */
540 final ArrayList<ProcessRecord> mProcessesToGc
541 = new ArrayList<ProcessRecord>();
542
543 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800544 * This is the process holding what we currently consider to be
545 * the "home" activity.
546 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700547 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800548
549 /**
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400550 * Packages that the user has asked to have run in screen size
551 * compatibility mode instead of filling the screen.
552 */
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -0700553 final CompatModePackages mCompatModePackages;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400554
555 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 * Set of PendingResultRecord objects that are currently active.
557 */
558 final HashSet mPendingResultRecords = new HashSet();
559
560 /**
561 * Set of IntentSenderRecord objects that are currently active.
562 */
563 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
564 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
565
566 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800567 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700568 * already logged DropBox entries for. Guarded by itself. If
569 * something (rogue user app) forces this over
570 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
571 */
572 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
573 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
574
575 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700576 * Strict Mode background batched logging state.
577 *
578 * The string buffer is guarded by itself, and its lock is also
579 * used to determine if another batched write is already
580 * in-flight.
581 */
582 private final StringBuilder mStrictModeBuffer = new StringBuilder();
583
584 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700585 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
586 */
587 private boolean mPendingBroadcastTimeoutMessage;
588
589 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 * Intent broadcast that we have tried to start, but are
591 * waiting for its application's process to be created. We only
592 * need one (instead of a list) because we always process broadcasts
593 * one at a time, so no others can be started while waiting for this
594 * one.
595 */
596 BroadcastRecord mPendingBroadcast = null;
597
598 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700599 * The receiver index that is pending, to restart the broadcast if needed.
600 */
601 int mPendingBroadcastRecvIndex;
602
603 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 * Keeps track of all IIntentReceivers that have been registered for
605 * broadcasts. Hash keys are the receiver IBinder, hash value is
606 * a ReceiverList.
607 */
608 final HashMap mRegisteredReceivers = new HashMap();
609
610 /**
611 * Resolver for broadcast intents to registered receivers.
612 * Holds BroadcastFilter (subclass of IntentFilter).
613 */
614 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
615 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
616 @Override
617 protected boolean allowFilterResult(
618 BroadcastFilter filter, List<BroadcastFilter> dest) {
619 IBinder target = filter.receiverList.receiver.asBinder();
620 for (int i=dest.size()-1; i>=0; i--) {
621 if (dest.get(i).receiverList.receiver.asBinder() == target) {
622 return false;
623 }
624 }
625 return true;
626 }
627 };
628
629 /**
630 * State of all active sticky broadcasts. Keys are the action of the
631 * sticky Intent, values are an ArrayList of all broadcasted intents with
632 * that action (which should usually be one).
633 */
634 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
635 new HashMap<String, ArrayList<Intent>>();
636
637 /**
638 * All currently running services.
639 */
640 final HashMap<ComponentName, ServiceRecord> mServices =
641 new HashMap<ComponentName, ServiceRecord>();
642
643 /**
644 * All currently running services indexed by the Intent used to start them.
645 */
646 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
647 new HashMap<Intent.FilterComparison, ServiceRecord>();
648
649 /**
650 * All currently bound service connections. Keys are the IBinder of
651 * the client's IServiceConnection.
652 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700653 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
654 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655
656 /**
657 * List of services that we have been asked to start,
658 * but haven't yet been able to. It is used to hold start requests
659 * while waiting for their corresponding application thread to get
660 * going.
661 */
662 final ArrayList<ServiceRecord> mPendingServices
663 = new ArrayList<ServiceRecord>();
664
665 /**
666 * List of services that are scheduled to restart following a crash.
667 */
668 final ArrayList<ServiceRecord> mRestartingServices
669 = new ArrayList<ServiceRecord>();
670
671 /**
672 * List of services that are in the process of being stopped.
673 */
674 final ArrayList<ServiceRecord> mStoppingServices
675 = new ArrayList<ServiceRecord>();
676
677 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700678 * Backup/restore process management
679 */
680 String mBackupAppName = null;
681 BackupRecord mBackupTarget = null;
682
683 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 * List of PendingThumbnailsRecord objects of clients who are still
685 * waiting to receive all of the thumbnails for a task.
686 */
687 final ArrayList mPendingThumbnails = new ArrayList();
688
689 /**
690 * List of HistoryRecord objects that have been finished and must
691 * still report back to a pending thumbnail receiver.
692 */
693 final ArrayList mCancelledThumbnails = new ArrayList();
694
695 /**
696 * All of the currently running global content providers. Keys are a
697 * string containing the provider name and values are a
698 * ContentProviderRecord object containing the data about it. Note
699 * that a single provider may be published under multiple names, so
700 * there may be multiple entries here for a single one in mProvidersByClass.
701 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700702 final HashMap<String, ContentProviderRecord> mProvidersByName
703 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704
705 /**
706 * All of the currently running global content providers. Keys are a
707 * string containing the provider's implementation class and values are a
708 * ContentProviderRecord object containing the data about it.
709 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700710 final HashMap<String, ContentProviderRecord> mProvidersByClass
711 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712
713 /**
714 * List of content providers who have clients waiting for them. The
715 * application is currently being launched and the provider will be
716 * removed from this list once it is published.
717 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700718 final ArrayList<ContentProviderRecord> mLaunchingProviders
719 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720
721 /**
722 * Global set of specific Uri permissions that have been granted.
723 */
724 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
725 = new SparseArray<HashMap<Uri, UriPermission>>();
726
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800727 CoreSettingsObserver mCoreSettingsObserver;
728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 /**
730 * Thread-local storage used to carry caller permissions over through
731 * indirect content-provider access.
732 * @see #ActivityManagerService.openContentUri()
733 */
734 private class Identity {
735 public int pid;
736 public int uid;
737
738 Identity(int _pid, int _uid) {
739 pid = _pid;
740 uid = _uid;
741 }
742 }
743 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
744
745 /**
746 * All information we have collected about the runtime performance of
747 * any user id that can impact battery performance.
748 */
749 final BatteryStatsService mBatteryStatsService;
750
751 /**
752 * information about component usage
753 */
754 final UsageStatsService mUsageStatsService;
755
756 /**
757 * Current configuration information. HistoryRecord objects are given
758 * a reference to this object to indicate which configuration they are
759 * currently running in, so this object must be kept immutable.
760 */
761 Configuration mConfiguration = new Configuration();
762
763 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800764 * Current sequencing integer of the configuration, for skipping old
765 * configurations.
766 */
767 int mConfigurationSeq = 0;
768
769 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700770 * Hardware-reported OpenGLES version.
771 */
772 final int GL_ES_VERSION;
773
774 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775 * List of initialization arguments to pass to all processes when binding applications to them.
776 * For example, references to the commonly used services.
777 */
778 HashMap<String, IBinder> mAppBindArgs;
779
780 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700781 * Temporary to avoid allocations. Protected by main lock.
782 */
783 final StringBuilder mStringBuilder = new StringBuilder(256);
784
785 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 * Used to control how we initialize the service.
787 */
788 boolean mStartRunning = false;
789 ComponentName mTopComponent;
790 String mTopAction;
791 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700792 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 boolean mSystemReady = false;
794 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700795 boolean mWaitingUpdate = false;
796 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700797 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700798 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799
800 Context mContext;
801
802 int mFactoryTest;
803
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700804 boolean mCheckedForSetup;
805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700807 * The time at which we will allow normal application switches again,
808 * after a call to {@link #stopAppSwitches()}.
809 */
810 long mAppSwitchesAllowedTime;
811
812 /**
813 * This is set to true after the first switch after mAppSwitchesAllowedTime
814 * is set; any switches after that will clear the time.
815 */
816 boolean mDidAppSwitch;
817
818 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700819 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700820 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700821 long mLastPowerCheckRealtime;
822
823 /**
824 * Last time (in uptime) at which we checked for power usage.
825 */
826 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700827
828 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 * Set while we are wanting to sleep, to prevent any
830 * activities from being started/resumed.
831 */
832 boolean mSleeping = false;
833
834 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700835 * Set if we are shutting down the system, similar to sleeping.
836 */
837 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838
839 /**
840 * Task identifier that activities are currently being started
841 * in. Incremented each time a new task is created.
842 * todo: Replace this with a TokenSpace class that generates non-repeating
843 * integers that won't wrap.
844 */
845 int mCurTask = 1;
846
847 /**
848 * Current sequence id for oom_adj computation traversal.
849 */
850 int mAdjSeq = 0;
851
852 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700853 * Current sequence id for process LRU updating.
854 */
855 int mLruSeq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856
857 /**
858 * System monitoring: number of processes that died since the last
859 * N procs were started.
860 */
861 int[] mProcDeaths = new int[20];
862
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700863 /**
864 * This is set if we had to do a delayed dexopt of an app before launching
865 * it, to increasing the ANR timeouts in that case.
866 */
867 boolean mDidDexOpt;
868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 String mDebugApp = null;
870 boolean mWaitForDebugger = false;
871 boolean mDebugTransient = false;
872 String mOrigDebugApp = null;
873 boolean mOrigWaitForDebugger = false;
874 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700875 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700877 final RemoteCallbackList<IActivityWatcher> mWatchers
878 = new RemoteCallbackList<IActivityWatcher>();
Jeff Sharkeya4620792011-05-20 15:29:23 -0700879
880 final RemoteCallbackList<IProcessObserver> mProcessObservers
881 = new RemoteCallbackList<IProcessObserver>();
882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 /**
884 * Callback of last caller to {@link #requestPss}.
885 */
886 Runnable mRequestPssCallback;
887
888 /**
889 * Remaining processes for which we are waiting results from the last
890 * call to {@link #requestPss}.
891 */
892 final ArrayList<ProcessRecord> mRequestPssList
893 = new ArrayList<ProcessRecord>();
894
895 /**
896 * Runtime statistics collection thread. This object's lock is used to
897 * protect all related state.
898 */
899 final Thread mProcessStatsThread;
900
901 /**
902 * Used to collect process stats when showing not responding dialog.
903 * Protected by mProcessStatsThread.
904 */
905 final ProcessStats mProcessStats = new ProcessStats(
906 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700907 final AtomicLong mLastCpuTime = new AtomicLong(0);
908 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 long mLastWriteTime = 0;
911
912 /**
913 * Set to true after the system has finished booting.
914 */
915 boolean mBooted = false;
916
917 int mProcessLimit = 0;
918
919 WindowManagerService mWindowManager;
920
921 static ActivityManagerService mSelf;
922 static ActivityThread mSystemThread;
923
924 private final class AppDeathRecipient implements IBinder.DeathRecipient {
925 final ProcessRecord mApp;
926 final int mPid;
927 final IApplicationThread mAppThread;
928
929 AppDeathRecipient(ProcessRecord app, int pid,
930 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800931 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 TAG, "New death recipient " + this
933 + " for thread " + thread.asBinder());
934 mApp = app;
935 mPid = pid;
936 mAppThread = thread;
937 }
938
939 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800940 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 TAG, "Death received in " + this
942 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943 synchronized(ActivityManagerService.this) {
944 appDiedLocked(mApp, mPid, mAppThread);
945 }
946 }
947 }
948
949 static final int SHOW_ERROR_MSG = 1;
950 static final int SHOW_NOT_RESPONDING_MSG = 2;
951 static final int SHOW_FACTORY_ERROR_MSG = 3;
952 static final int UPDATE_CONFIGURATION_MSG = 4;
953 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
954 static final int WAIT_FOR_DEBUGGER_MSG = 6;
955 static final int BROADCAST_INTENT_MSG = 7;
956 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 static final int SERVICE_TIMEOUT_MSG = 12;
958 static final int UPDATE_TIME_ZONE = 13;
959 static final int SHOW_UID_ERROR_MSG = 14;
960 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700962 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700963 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800964 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700965 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
966 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700967 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700968 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700969 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700970 static final int UPDATE_HTTP_PROXY = 29;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700971 static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
Dianne Hackborn36f80f32011-05-31 18:26:45 -0700972 static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
973 static final int DISPATCH_PROCESS_DIED = 32;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974
975 AlertDialog mUidAlert;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700976 CompatModeDialog mCompatModeDialog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977
978 final Handler mHandler = new Handler() {
979 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800980 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 //}
982
983 public void handleMessage(Message msg) {
984 switch (msg.what) {
985 case SHOW_ERROR_MSG: {
986 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 synchronized (ActivityManagerService.this) {
988 ProcessRecord proc = (ProcessRecord)data.get("app");
989 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800990 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 return;
992 }
993 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700994 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800995 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 d.show();
997 proc.crashDialog = d;
998 } else {
999 // The device is asleep, so just pretend that the user
1000 // saw a crash dialog and hit "force quit".
1001 res.set(0);
1002 }
1003 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001004
1005 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 } break;
1007 case SHOW_NOT_RESPONDING_MSG: {
1008 synchronized (ActivityManagerService.this) {
1009 HashMap data = (HashMap) msg.obj;
1010 ProcessRecord proc = (ProcessRecord)data.get("app");
1011 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001012 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 return;
1014 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001015
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001016 Intent intent = new Intent("android.intent.action.ANR");
1017 if (!mProcessesReady) {
1018 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1019 }
1020 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001021 null, null, 0, null, null, null,
1022 false, false, MY_PID, Process.SYSTEM_UID);
1023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001025 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 d.show();
1027 proc.anrDialog = d;
1028 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001029
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001030 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001032 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1033 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1034 synchronized (ActivityManagerService.this) {
1035 ProcessRecord proc = (ProcessRecord) data.get("app");
1036 if (proc == null) {
1037 Slog.e(TAG, "App not found when showing strict mode dialog.");
1038 break;
1039 }
1040 if (proc.crashDialog != null) {
1041 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1042 return;
1043 }
1044 AppErrorResult res = (AppErrorResult) data.get("result");
1045 if (!mSleeping && !mShuttingDown) {
1046 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1047 d.show();
1048 proc.crashDialog = d;
1049 } else {
1050 // The device is asleep, so just pretend that the user
1051 // saw a crash dialog and hit "force quit".
1052 res.set(0);
1053 }
1054 }
1055 ensureBootCompleted();
1056 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 case SHOW_FACTORY_ERROR_MSG: {
1058 Dialog d = new FactoryErrorDialog(
1059 mContext, msg.getData().getCharSequence("msg"));
1060 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001061 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 } break;
1063 case UPDATE_CONFIGURATION_MSG: {
1064 final ContentResolver resolver = mContext.getContentResolver();
1065 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1066 } break;
1067 case GC_BACKGROUND_PROCESSES_MSG: {
1068 synchronized (ActivityManagerService.this) {
1069 performAppGcsIfAppropriateLocked();
1070 }
1071 } break;
1072 case WAIT_FOR_DEBUGGER_MSG: {
1073 synchronized (ActivityManagerService.this) {
1074 ProcessRecord app = (ProcessRecord)msg.obj;
1075 if (msg.arg1 != 0) {
1076 if (!app.waitedForDebugger) {
1077 Dialog d = new AppWaitingForDebuggerDialog(
1078 ActivityManagerService.this,
1079 mContext, app);
1080 app.waitDialog = d;
1081 app.waitedForDebugger = true;
1082 d.show();
1083 }
1084 } else {
1085 if (app.waitDialog != null) {
1086 app.waitDialog.dismiss();
1087 app.waitDialog = null;
1088 }
1089 }
1090 }
1091 } break;
1092 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001093 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 TAG, "Received BROADCAST_INTENT_MSG");
1095 processNextBroadcast(true);
1096 } break;
1097 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001098 synchronized (ActivityManagerService.this) {
1099 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001103 if (mDidDexOpt) {
1104 mDidDexOpt = false;
1105 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1106 nmsg.obj = msg.obj;
1107 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1108 return;
1109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 serviceTimeout((ProcessRecord)msg.obj);
1111 } break;
1112 case UPDATE_TIME_ZONE: {
1113 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001114 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1115 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 if (r.thread != null) {
1117 try {
1118 r.thread.updateTimeZone();
1119 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001120 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 }
1122 }
1123 }
1124 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001125 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001126 case CLEAR_DNS_CACHE: {
1127 synchronized (ActivityManagerService.this) {
1128 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1129 ProcessRecord r = mLruProcesses.get(i);
1130 if (r.thread != null) {
1131 try {
1132 r.thread.clearDnsCache();
1133 } catch (RemoteException ex) {
1134 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1135 }
1136 }
1137 }
1138 }
1139 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001140 case UPDATE_HTTP_PROXY: {
1141 ProxyProperties proxy = (ProxyProperties)msg.obj;
1142 String host = "";
1143 String port = "";
1144 String exclList = "";
1145 if (proxy != null) {
1146 host = proxy.getHost();
1147 port = Integer.toString(proxy.getPort());
1148 exclList = proxy.getExclusionList();
1149 }
1150 synchronized (ActivityManagerService.this) {
1151 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1152 ProcessRecord r = mLruProcesses.get(i);
1153 if (r.thread != null) {
1154 try {
1155 r.thread.setHttpProxy(host, port, exclList);
1156 } catch (RemoteException ex) {
1157 Slog.w(TAG, "Failed to update http proxy for: " +
1158 r.info.processName);
1159 }
1160 }
1161 }
1162 }
1163 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 case SHOW_UID_ERROR_MSG: {
1165 // XXX This is a temporary dialog, no need to localize.
1166 AlertDialog d = new BaseErrorDialog(mContext);
1167 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1168 d.setCancelable(false);
1169 d.setTitle("System UIDs Inconsistent");
1170 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 +02001171 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1173 mUidAlert = d;
1174 d.show();
1175 } break;
1176 case IM_FEELING_LUCKY_MSG: {
1177 if (mUidAlert != null) {
1178 mUidAlert.dismiss();
1179 mUidAlert = null;
1180 }
1181 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001183 if (mDidDexOpt) {
1184 mDidDexOpt = false;
1185 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1186 nmsg.obj = msg.obj;
1187 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1188 return;
1189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 ProcessRecord app = (ProcessRecord)msg.obj;
1191 synchronized (ActivityManagerService.this) {
1192 processStartTimedOutLocked(app);
1193 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001194 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001195 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1196 synchronized (ActivityManagerService.this) {
1197 doPendingActivityLaunchesLocked(true);
1198 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001199 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001200 case KILL_APPLICATION_MSG: {
1201 synchronized (ActivityManagerService.this) {
1202 int uid = msg.arg1;
1203 boolean restart = (msg.arg2 == 1);
1204 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001205 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001206 }
1207 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001208 case FINALIZE_PENDING_INTENT_MSG: {
1209 ((PendingIntentRecord)msg.obj).completeFinalize();
1210 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001211 case POST_HEAVY_NOTIFICATION_MSG: {
1212 INotificationManager inm = NotificationManager.getService();
1213 if (inm == null) {
1214 return;
1215 }
1216
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001217 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001218 ProcessRecord process = root.app;
1219 if (process == null) {
1220 return;
1221 }
1222
1223 try {
1224 Context context = mContext.createPackageContext(process.info.packageName, 0);
1225 String text = mContext.getString(R.string.heavy_weight_notification,
1226 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1227 Notification notification = new Notification();
1228 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1229 notification.when = 0;
1230 notification.flags = Notification.FLAG_ONGOING_EVENT;
1231 notification.tickerText = text;
1232 notification.defaults = 0; // please be quiet
1233 notification.sound = null;
1234 notification.vibrate = null;
1235 notification.setLatestEventInfo(context, text,
1236 mContext.getText(R.string.heavy_weight_notification_detail),
1237 PendingIntent.getActivity(mContext, 0, root.intent,
1238 PendingIntent.FLAG_CANCEL_CURRENT));
1239
1240 try {
1241 int[] outId = new int[1];
1242 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1243 notification, outId);
1244 } catch (RuntimeException e) {
1245 Slog.w(ActivityManagerService.TAG,
1246 "Error showing notification for heavy-weight app", e);
1247 } catch (RemoteException e) {
1248 }
1249 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001250 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001251 }
1252 } break;
1253 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1254 INotificationManager inm = NotificationManager.getService();
1255 if (inm == null) {
1256 return;
1257 }
1258 try {
1259 inm.cancelNotification("android",
1260 R.string.heavy_weight_notification);
1261 } catch (RuntimeException e) {
1262 Slog.w(ActivityManagerService.TAG,
1263 "Error canceling notification for service", e);
1264 } catch (RemoteException e) {
1265 }
1266 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001267 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1268 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001269 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001270 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001271 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1272 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001273 }
1274 } break;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001275 case SHOW_COMPAT_MODE_DIALOG_MSG: {
1276 synchronized (ActivityManagerService.this) {
1277 ActivityRecord ar = (ActivityRecord)msg.obj;
1278 if (mCompatModeDialog != null) {
1279 if (mCompatModeDialog.mAppInfo.packageName.equals(
1280 ar.info.applicationInfo.packageName)) {
1281 return;
1282 }
1283 mCompatModeDialog.dismiss();
1284 mCompatModeDialog = null;
1285 }
1286 if (ar != null) {
1287 if (mCompatModePackages.getPackageAskCompatModeLocked(
1288 ar.packageName)) {
1289 int mode = mCompatModePackages.computeCompatModeLocked(
1290 ar.info.applicationInfo);
1291 if (mode == ActivityManager.COMPAT_MODE_DISABLED
1292 || mode == ActivityManager.COMPAT_MODE_ENABLED) {
1293 mCompatModeDialog = new CompatModeDialog(
1294 ActivityManagerService.this, mContext,
1295 ar.info.applicationInfo);
1296 mCompatModeDialog.show();
1297 }
1298 }
1299 }
1300 }
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001301 break;
1302 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001303 case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001304 final ProcessRecord app = (ProcessRecord) msg.obj;
Jeff Sharkeya4620792011-05-20 15:29:23 -07001305 final boolean foregroundActivities = msg.arg1 != 0;
1306 dispatchForegroundActivitiesChanged(
1307 app.pid, app.info.uid, foregroundActivities);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001308 break;
1309 }
1310 case DISPATCH_PROCESS_DIED: {
1311 final ProcessRecord app = (ProcessRecord) msg.obj;
Jeff Sharkeya4620792011-05-20 15:29:23 -07001312 dispatchProcessDied(app.pid, app.info.uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001313 break;
1314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001315 }
1316 }
1317 };
1318
1319 public static void setSystemProcess() {
1320 try {
1321 ActivityManagerService m = mSelf;
1322
1323 ServiceManager.addService("activity", m);
1324 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07001325 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001326 if (MONITOR_CPU_USAGE) {
1327 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 ServiceManager.addService("permission", new PermissionController(m));
1330
1331 ApplicationInfo info =
1332 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001333 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001334 mSystemThread.installSystemApplicationInfo(info);
1335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 synchronized (mSelf) {
1337 ProcessRecord app = mSelf.newProcessRecordLocked(
1338 mSystemThread.getApplicationThread(), info,
1339 info.processName);
1340 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001341 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 app.maxAdj = SYSTEM_ADJ;
1343 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1344 synchronized (mSelf.mPidsSelfLocked) {
1345 mSelf.mPidsSelfLocked.put(app.pid, app);
1346 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001347 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 }
1349 } catch (PackageManager.NameNotFoundException e) {
1350 throw new RuntimeException(
1351 "Unable to find android system package", e);
1352 }
1353 }
1354
1355 public void setWindowManager(WindowManagerService wm) {
1356 mWindowManager = wm;
1357 }
1358
1359 public static final Context main(int factoryTest) {
1360 AThread thr = new AThread();
1361 thr.start();
1362
1363 synchronized (thr) {
1364 while (thr.mService == null) {
1365 try {
1366 thr.wait();
1367 } catch (InterruptedException e) {
1368 }
1369 }
1370 }
1371
1372 ActivityManagerService m = thr.mService;
1373 mSelf = m;
1374 ActivityThread at = ActivityThread.systemMain();
1375 mSystemThread = at;
1376 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001377 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 m.mContext = context;
1379 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001380 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381
1382 m.mBatteryStatsService.publish(context);
1383 m.mUsageStatsService.publish(context);
1384
1385 synchronized (thr) {
1386 thr.mReady = true;
1387 thr.notifyAll();
1388 }
1389
1390 m.startRunning(null, null, null, null);
1391
1392 return context;
1393 }
1394
1395 public static ActivityManagerService self() {
1396 return mSelf;
1397 }
1398
1399 static class AThread extends Thread {
1400 ActivityManagerService mService;
1401 boolean mReady = false;
1402
1403 public AThread() {
1404 super("ActivityManager");
1405 }
1406
1407 public void run() {
1408 Looper.prepare();
1409
1410 android.os.Process.setThreadPriority(
1411 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001412 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413
1414 ActivityManagerService m = new ActivityManagerService();
1415
1416 synchronized (this) {
1417 mService = m;
1418 notifyAll();
1419 }
1420
1421 synchronized (this) {
1422 while (!mReady) {
1423 try {
1424 wait();
1425 } catch (InterruptedException e) {
1426 }
1427 }
1428 }
1429
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001430 // For debug builds, log event loop stalls to dropbox for analysis.
1431 if (StrictMode.conditionallyEnableDebugLogging()) {
1432 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1433 }
1434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 Looper.loop();
1436 }
1437 }
1438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 static class MemBinder extends Binder {
1440 ActivityManagerService mActivityManagerService;
1441 MemBinder(ActivityManagerService activityManagerService) {
1442 mActivityManagerService = activityManagerService;
1443 }
1444
1445 @Override
1446 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001447 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 }
1449 }
1450
Chet Haase9c1e23b2011-03-24 10:51:31 -07001451 static class GraphicsBinder extends Binder {
1452 ActivityManagerService mActivityManagerService;
1453 GraphicsBinder(ActivityManagerService activityManagerService) {
1454 mActivityManagerService = activityManagerService;
1455 }
1456
1457 @Override
1458 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001459 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07001460 }
1461 }
1462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 static class CpuBinder extends Binder {
1464 ActivityManagerService mActivityManagerService;
1465 CpuBinder(ActivityManagerService activityManagerService) {
1466 mActivityManagerService = activityManagerService;
1467 }
1468
1469 @Override
1470 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1471 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001472 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1473 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1474 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 }
1476 }
1477 }
1478
1479 private ActivityManagerService() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001480 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 File dataDir = Environment.getDataDirectory();
1483 File systemDir = new File(dataDir, "system");
1484 systemDir.mkdirs();
1485 mBatteryStatsService = new BatteryStatsService(new File(
1486 systemDir, "batterystats.bin").toString());
1487 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001488 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001489 mOnBattery = DEBUG_POWER ? true
1490 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001491 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001493 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001494 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495
Jack Palevichb90d28c2009-07-22 15:35:24 -07001496 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1497 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1498
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001499 mConfiguration.setToDefaults();
1500 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 mProcessStats.init();
1502
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07001503 mCompatModePackages = new CompatModePackages(this, systemDir);
1504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 // Add ourself to the Watchdog monitors.
1506 Watchdog.getInstance().addMonitor(this);
1507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 mProcessStatsThread = new Thread("ProcessStats") {
1509 public void run() {
1510 while (true) {
1511 try {
1512 try {
1513 synchronized(this) {
1514 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001515 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001517 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 // + ", write delay=" + nextWriteDelay);
1519 if (nextWriteDelay < nextCpuDelay) {
1520 nextCpuDelay = nextWriteDelay;
1521 }
1522 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001523 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 this.wait(nextCpuDelay);
1525 }
1526 }
1527 } catch (InterruptedException e) {
1528 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 updateCpuStatsNow();
1530 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001531 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 }
1533 }
1534 }
1535 };
1536 mProcessStatsThread.start();
1537 }
1538
1539 @Override
1540 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1541 throws RemoteException {
1542 try {
1543 return super.onTransact(code, data, reply, flags);
1544 } catch (RuntimeException e) {
1545 // The activity manager only throws security exceptions, so let's
1546 // log all others.
1547 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001548 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 }
1550 throw e;
1551 }
1552 }
1553
1554 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001555 final long now = SystemClock.uptimeMillis();
1556 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1557 return;
1558 }
1559 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1560 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 mProcessStatsThread.notify();
1562 }
1563 }
1564 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 void updateCpuStatsNow() {
1567 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001568 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 final long now = SystemClock.uptimeMillis();
1570 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001573 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1574 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 haveNewCpuStats = true;
1576 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001577 //Slog.i(TAG, mProcessStats.printCurrentState());
1578 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 // + mProcessStats.getTotalCpuPercent() + "%");
1580
Joe Onorato8a9b2202010-02-26 18:56:32 -08001581 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 if ("true".equals(SystemProperties.get("events.cpu"))) {
1583 int user = mProcessStats.getLastUserTime();
1584 int system = mProcessStats.getLastSystemTime();
1585 int iowait = mProcessStats.getLastIoWaitTime();
1586 int irq = mProcessStats.getLastIrqTime();
1587 int softIrq = mProcessStats.getLastSoftIrqTime();
1588 int idle = mProcessStats.getLastIdleTime();
1589
1590 int total = user + system + iowait + irq + softIrq + idle;
1591 if (total == 0) total = 1;
1592
Doug Zongker2bec3d42009-12-04 12:52:44 -08001593 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 ((user+system+iowait+irq+softIrq) * 100) / total,
1595 (user * 100) / total,
1596 (system * 100) / total,
1597 (iowait * 100) / total,
1598 (irq * 100) / total,
1599 (softIrq * 100) / total);
1600 }
1601 }
1602
Amith Yamasanie43530a2009-08-21 13:11:37 -07001603 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001604 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001605 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 synchronized(mPidsSelfLocked) {
1607 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001608 if (mOnBattery) {
1609 int perc = bstats.startAddingCpuLocked();
1610 int totalUTime = 0;
1611 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001612 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001614 ProcessStats.Stats st = mProcessStats.getStats(i);
1615 if (!st.working) {
1616 continue;
1617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001619 int otherUTime = (st.rel_utime*perc)/100;
1620 int otherSTime = (st.rel_stime*perc)/100;
1621 totalUTime += otherUTime;
1622 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 if (pr != null) {
1624 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001625 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1626 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001627 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001628 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001629 } else {
1630 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001631 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001632 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001633 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1634 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001635 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001636 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 }
1638 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001639 bstats.finishAddingCpuLocked(perc, totalUTime,
1640 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 }
1642 }
1643 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1646 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001647 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 }
1649 }
1650 }
1651 }
1652
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001653 @Override
1654 public void batteryNeedsCpuUpdate() {
1655 updateCpuStatsNow();
1656 }
1657
1658 @Override
1659 public void batteryPowerChanged(boolean onBattery) {
1660 // When plugging in, update the CPU stats first before changing
1661 // the plug state.
1662 updateCpuStatsNow();
1663 synchronized (this) {
1664 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001665 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001666 }
1667 }
1668 }
1669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 /**
1671 * Initialize the application bind args. These are passed to each
1672 * process when the bindApplication() IPC is sent to the process. They're
1673 * lazily setup to make sure the services are running when they're asked for.
1674 */
1675 private HashMap<String, IBinder> getCommonServicesLocked() {
1676 if (mAppBindArgs == null) {
1677 mAppBindArgs = new HashMap<String, IBinder>();
1678
1679 // Setup the application init args
1680 mAppBindArgs.put("package", ServiceManager.getService("package"));
1681 mAppBindArgs.put("window", ServiceManager.getService("window"));
1682 mAppBindArgs.put(Context.ALARM_SERVICE,
1683 ServiceManager.getService(Context.ALARM_SERVICE));
1684 }
1685 return mAppBindArgs;
1686 }
1687
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001688 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001689 if (mFocusedActivity != r) {
1690 mFocusedActivity = r;
1691 mWindowManager.setFocusedApp(r, true);
1692 }
1693 }
1694
Dianne Hackborn906497c2010-05-10 15:57:38 -07001695 private final void updateLruProcessInternalLocked(ProcessRecord app,
1696 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001698 int lrui = mLruProcesses.indexOf(app);
1699 if (lrui >= 0) mLruProcesses.remove(lrui);
1700
1701 int i = mLruProcesses.size()-1;
1702 int skipTop = 0;
1703
Dianne Hackborn906497c2010-05-10 15:57:38 -07001704 app.lruSeq = mLruSeq;
1705
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001706 // compute the new weight for this process.
1707 if (updateActivityTime) {
1708 app.lastActivityTime = SystemClock.uptimeMillis();
1709 }
1710 if (app.activities.size() > 0) {
1711 // If this process has activities, we more strongly want to keep
1712 // it around.
1713 app.lruWeight = app.lastActivityTime;
1714 } else if (app.pubProviders.size() > 0) {
1715 // If this process contains content providers, we want to keep
1716 // it a little more strongly.
1717 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1718 // Also don't let it kick out the first few "real" hidden processes.
1719 skipTop = MIN_HIDDEN_APPS;
1720 } else {
1721 // If this process doesn't have activities, we less strongly
1722 // want to keep it around, and generally want to avoid getting
1723 // in front of any very recently used activities.
1724 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1725 // Also don't let it kick out the first few "real" hidden processes.
1726 skipTop = MIN_HIDDEN_APPS;
1727 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001728
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001729 while (i >= 0) {
1730 ProcessRecord p = mLruProcesses.get(i);
1731 // If this app shouldn't be in front of the first N background
1732 // apps, then skip over that many that are currently hidden.
1733 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1734 skipTop--;
1735 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001736 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001737 mLruProcesses.add(i+1, app);
1738 break;
1739 }
1740 i--;
1741 }
1742 if (i < 0) {
1743 mLruProcesses.add(0, app);
1744 }
1745
Dianne Hackborn906497c2010-05-10 15:57:38 -07001746 // If the app is currently using a content provider or service,
1747 // bump those processes as well.
1748 if (app.connections.size() > 0) {
1749 for (ConnectionRecord cr : app.connections) {
1750 if (cr.binding != null && cr.binding.service != null
1751 && cr.binding.service.app != null
1752 && cr.binding.service.app.lruSeq != mLruSeq) {
1753 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1754 updateActivityTime, i+1);
1755 }
1756 }
1757 }
1758 if (app.conProviders.size() > 0) {
1759 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1760 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1761 updateLruProcessInternalLocked(cpr.app, oomAdj,
1762 updateActivityTime, i+1);
1763 }
1764 }
1765 }
1766
Joe Onorato8a9b2202010-02-26 18:56:32 -08001767 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 if (oomAdj) {
1769 updateOomAdjLocked();
1770 }
1771 }
1772
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001773 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001774 boolean oomAdj, boolean updateActivityTime) {
1775 mLruSeq++;
1776 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1777 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001778
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001779 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 String processName, int uid) {
1781 if (uid == Process.SYSTEM_UID) {
1782 // The system gets to run in any process. If there are multiple
1783 // processes with the same uid, just pick the first (this
1784 // should never happen).
1785 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1786 processName);
1787 return procs != null ? procs.valueAt(0) : null;
1788 }
1789 ProcessRecord proc = mProcessNames.get(processName, uid);
1790 return proc;
1791 }
1792
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001793 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001794 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001795 try {
1796 if (pm.performDexOpt(packageName)) {
1797 mDidDexOpt = true;
1798 }
1799 } catch (RemoteException e) {
1800 }
1801 }
1802
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001803 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 int transit = mWindowManager.getPendingAppTransition();
1805 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1806 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1807 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1808 }
1809
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001810 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001812 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001813 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1814 // We don't have to do anything more if:
1815 // (1) There is an existing application record; and
1816 // (2) The caller doesn't think it is dead, OR there is no thread
1817 // object attached to it so we know it couldn't have crashed; and
1818 // (3) There is a pid assigned to it, so it is either starting or
1819 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001820 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001821 + " app=" + app + " knownToBeDead=" + knownToBeDead
1822 + " thread=" + (app != null ? app.thread : null)
1823 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001824 if (app != null && app.pid > 0) {
1825 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001826 // We already have the app running, or are waiting for it to
1827 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001828 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001829 return app;
1830 } else {
1831 // An application record is attached to a previous process,
1832 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001833 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001834 handleAppDiedLocked(app, true);
1835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001836 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838 String hostingNameStr = hostingName != null
1839 ? hostingName.flattenToShortString() : null;
1840
1841 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1842 // If we are in the background, then check to see if this process
1843 // is bad. If so, we will just silently fail.
1844 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001845 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1846 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 return null;
1848 }
1849 } else {
1850 // When the user is explicitly starting a process, then clear its
1851 // crash count so that we won't make it bad until they see at
1852 // least one crash dialog again, and make the process good again
1853 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001854 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1855 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 mProcessCrashTimes.remove(info.processName, info.uid);
1857 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001858 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859 info.processName);
1860 mBadProcesses.remove(info.processName, info.uid);
1861 if (app != null) {
1862 app.bad = false;
1863 }
1864 }
1865 }
1866
1867 if (app == null) {
1868 app = newProcessRecordLocked(null, info, processName);
1869 mProcessNames.put(processName, info.uid, app);
1870 } else {
1871 // If this is a new package in the process, add the package to the list
1872 app.addPackage(info.packageName);
1873 }
1874
1875 // If the system is not ready yet, then hold off on starting this
1876 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001877 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001878 && !isAllowedWhileBooting(info)
1879 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001880 if (!mProcessesOnHold.contains(app)) {
1881 mProcessesOnHold.add(app);
1882 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001883 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001884 return app;
1885 }
1886
1887 startProcessLocked(app, hostingType, hostingNameStr);
1888 return (app.pid != 0) ? app : null;
1889 }
1890
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001891 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1892 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1893 }
1894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 private final void startProcessLocked(ProcessRecord app,
1896 String hostingType, String hostingNameStr) {
1897 if (app.pid > 0 && app.pid != MY_PID) {
1898 synchronized (mPidsSelfLocked) {
1899 mPidsSelfLocked.remove(app.pid);
1900 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1901 }
1902 app.pid = 0;
1903 }
1904
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001905 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1906 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001907 mProcessesOnHold.remove(app);
1908
1909 updateCpuStats();
1910
1911 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1912 mProcDeaths[0] = 0;
1913
1914 try {
1915 int uid = app.info.uid;
1916 int[] gids = null;
1917 try {
1918 gids = mContext.getPackageManager().getPackageGids(
1919 app.info.packageName);
1920 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001921 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 }
1923 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1924 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1925 && mTopComponent != null
1926 && app.processName.equals(mTopComponent.getPackageName())) {
1927 uid = 0;
1928 }
1929 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1930 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1931 uid = 0;
1932 }
1933 }
1934 int debugFlags = 0;
1935 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1936 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1937 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001938 // Run the app in safe mode if its manifest requests so or the
1939 // system is booted in safe mode.
1940 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1941 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001942 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001944 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1945 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1946 }
1947 if ("1".equals(SystemProperties.get("debug.assert"))) {
1948 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1949 }
1950 int pid = Process.start("android.app.ActivityThread",
Jeff Brownebed7d62011-05-16 17:08:42 -07001951 app.processName, uid, uid, gids, debugFlags, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001952 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1953 synchronized (bs) {
1954 if (bs.isOnBattery()) {
1955 app.batteryStats.incStartsLocked();
1956 }
1957 }
1958
Doug Zongker2bec3d42009-12-04 12:52:44 -08001959 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001960 app.processName, hostingType,
1961 hostingNameStr != null ? hostingNameStr : "");
1962
1963 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001964 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 }
1966
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001967 StringBuilder buf = mStringBuilder;
1968 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001969 buf.append("Start proc ");
1970 buf.append(app.processName);
1971 buf.append(" for ");
1972 buf.append(hostingType);
1973 if (hostingNameStr != null) {
1974 buf.append(" ");
1975 buf.append(hostingNameStr);
1976 }
1977 buf.append(": pid=");
1978 buf.append(pid);
1979 buf.append(" uid=");
1980 buf.append(uid);
1981 buf.append(" gids={");
1982 if (gids != null) {
1983 for (int gi=0; gi<gids.length; gi++) {
1984 if (gi != 0) buf.append(", ");
1985 buf.append(gids[gi]);
1986
1987 }
1988 }
1989 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001990 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001991 if (pid == 0 || pid == MY_PID) {
1992 // Processes are being emulated with threads.
1993 app.pid = MY_PID;
1994 app.removed = false;
1995 mStartingProcesses.add(app);
1996 } else if (pid > 0) {
1997 app.pid = pid;
1998 app.removed = false;
1999 synchronized (mPidsSelfLocked) {
2000 this.mPidsSelfLocked.put(pid, app);
2001 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2002 msg.obj = app;
2003 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2004 }
2005 } else {
2006 app.pid = 0;
2007 RuntimeException e = new RuntimeException(
2008 "Failure starting process " + app.processName
2009 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002010 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002011 }
2012 } catch (RuntimeException e) {
2013 // XXX do better error recovery.
2014 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002015 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002016 }
2017 }
2018
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002019 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 if (resumed) {
2021 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2022 } else {
2023 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2024 }
2025 }
2026
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002027 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002028 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2029 && mTopAction == null) {
2030 // We are running in factory test mode, but unable to find
2031 // the factory test app, so just sit around displaying the
2032 // error message and don't try to start anything.
2033 return false;
2034 }
2035 Intent intent = new Intent(
2036 mTopAction,
2037 mTopData != null ? Uri.parse(mTopData) : null);
2038 intent.setComponent(mTopComponent);
2039 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2040 intent.addCategory(Intent.CATEGORY_HOME);
2041 }
2042 ActivityInfo aInfo =
2043 intent.resolveActivityInfo(mContext.getPackageManager(),
2044 STOCK_PM_FLAGS);
2045 if (aInfo != null) {
2046 intent.setComponent(new ComponentName(
2047 aInfo.applicationInfo.packageName, aInfo.name));
2048 // Don't do this if the home app is currently being
2049 // instrumented.
2050 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2051 aInfo.applicationInfo.uid);
2052 if (app == null || app.instrumentationClass == null) {
2053 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002054 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002055 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002056 }
2057 }
2058
2059
2060 return true;
2061 }
2062
2063 /**
2064 * Starts the "new version setup screen" if appropriate.
2065 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002066 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002067 // Only do this once per boot.
2068 if (mCheckedForSetup) {
2069 return;
2070 }
2071
2072 // We will show this screen if the current one is a different
2073 // version than the last one shown, and we are not running in
2074 // low-level factory test mode.
2075 final ContentResolver resolver = mContext.getContentResolver();
2076 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2077 Settings.Secure.getInt(resolver,
2078 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2079 mCheckedForSetup = true;
2080
2081 // See if we should be showing the platform update setup UI.
2082 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2083 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2084 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2085
2086 // We don't allow third party apps to replace this.
2087 ResolveInfo ri = null;
2088 for (int i=0; ris != null && i<ris.size(); i++) {
2089 if ((ris.get(i).activityInfo.applicationInfo.flags
2090 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2091 ri = ris.get(i);
2092 break;
2093 }
2094 }
2095
2096 if (ri != null) {
2097 String vers = ri.activityInfo.metaData != null
2098 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2099 : null;
2100 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2101 vers = ri.activityInfo.applicationInfo.metaData.getString(
2102 Intent.METADATA_SETUP_VERSION);
2103 }
2104 String lastVers = Settings.Secure.getString(
2105 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2106 if (vers != null && !vers.equals(lastVers)) {
2107 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2108 intent.setComponent(new ComponentName(
2109 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002110 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002111 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002112 }
2113 }
2114 }
2115 }
2116
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002117 CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002118 return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002119 }
2120
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002121 public int getFrontActivityScreenCompatMode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002122 synchronized (this) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002123 return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
2124 }
2125 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002126
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002127 public void setFrontActivityScreenCompatMode(int mode) {
2128 synchronized (this) {
2129 mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
2130 }
2131 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002132
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002133 public int getPackageScreenCompatMode(String packageName) {
2134 synchronized (this) {
2135 return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
2136 }
2137 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002138
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002139 public void setPackageScreenCompatMode(String packageName, int mode) {
2140 synchronized (this) {
2141 mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002142 }
2143 }
2144
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002145 public boolean getPackageAskScreenCompat(String packageName) {
2146 synchronized (this) {
2147 return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
2148 }
2149 }
2150
2151 public void setPackageAskScreenCompat(String packageName, boolean ask) {
2152 synchronized (this) {
2153 mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
2154 }
2155 }
2156
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002157 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002158 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002159
2160 final int identHash = System.identityHashCode(r);
2161 updateUsageStats(r, true);
2162
2163 int i = mWatchers.beginBroadcast();
2164 while (i > 0) {
2165 i--;
2166 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2167 if (w != null) {
2168 try {
2169 w.activityResuming(identHash);
2170 } catch (RemoteException e) {
2171 }
2172 }
2173 }
2174 mWatchers.finishBroadcast();
2175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176
Jeff Sharkeya4620792011-05-20 15:29:23 -07002177 private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2178 int i = mProcessObservers.beginBroadcast();
2179 while (i > 0) {
2180 i--;
2181 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2182 if (observer != null) {
2183 try {
2184 observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
2185 } catch (RemoteException e) {
2186 }
2187 }
2188 }
2189 mProcessObservers.finishBroadcast();
2190 }
2191
2192 private void dispatchProcessDied(int pid, int uid) {
2193 int i = mProcessObservers.beginBroadcast();
2194 while (i > 0) {
2195 i--;
2196 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2197 if (observer != null) {
2198 try {
2199 observer.onProcessDied(pid, uid);
2200 } catch (RemoteException e) {
2201 }
2202 }
2203 }
2204 mProcessObservers.finishBroadcast();
2205 }
2206
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002207 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002208 final int N = mPendingActivityLaunches.size();
2209 if (N <= 0) {
2210 return;
2211 }
2212 for (int i=0; i<N; i++) {
2213 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002214 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002215 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2216 doResume && i == (N-1));
2217 }
2218 mPendingActivityLaunches.clear();
2219 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002220
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002221 public final int startActivity(IApplicationThread caller,
2222 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2223 int grantedMode, IBinder resultTo,
2224 String resultWho, int requestCode, boolean onlyIfNeeded,
2225 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002226 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002227 grantedUriPermissions, grantedMode, resultTo, resultWho,
2228 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002229 }
2230
2231 public final WaitResult startActivityAndWait(IApplicationThread caller,
2232 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2233 int grantedMode, IBinder resultTo,
2234 String resultWho, int requestCode, boolean onlyIfNeeded,
2235 boolean debug) {
2236 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002237 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002238 grantedUriPermissions, grantedMode, resultTo, resultWho,
2239 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002240 return res;
2241 }
2242
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002243 public final int startActivityWithConfig(IApplicationThread caller,
2244 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2245 int grantedMode, IBinder resultTo,
2246 String resultWho, int requestCode, boolean onlyIfNeeded,
2247 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002248 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002249 grantedUriPermissions, grantedMode, resultTo, resultWho,
2250 requestCode, onlyIfNeeded, debug, null, config);
2251 }
2252
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002253 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002254 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002255 IBinder resultTo, String resultWho, int requestCode,
2256 int flagsMask, int flagsValues) {
2257 // Refuse possible leaked file descriptors
2258 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2259 throw new IllegalArgumentException("File descriptors passed in Intent");
2260 }
2261
2262 IIntentSender sender = intent.getTarget();
2263 if (!(sender instanceof PendingIntentRecord)) {
2264 throw new IllegalArgumentException("Bad PendingIntent object");
2265 }
2266
2267 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002268
2269 synchronized (this) {
2270 // If this is coming from the currently resumed activity, it is
2271 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002272 if (mMainStack.mResumedActivity != null
2273 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002274 Binder.getCallingUid()) {
2275 mAppSwitchesAllowedTime = 0;
2276 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002277 }
2278
2279 return pir.sendInner(0, fillInIntent, resolvedType,
2280 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2281 }
2282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002283 public boolean startNextMatchingActivity(IBinder callingActivity,
2284 Intent intent) {
2285 // Refuse possible leaked file descriptors
2286 if (intent != null && intent.hasFileDescriptors() == true) {
2287 throw new IllegalArgumentException("File descriptors passed in Intent");
2288 }
2289
2290 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002291 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292 if (index < 0) {
2293 return false;
2294 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002295 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002296 if (r.app == null || r.app.thread == null) {
2297 // The caller is not running... d'oh!
2298 return false;
2299 }
2300 intent = new Intent(intent);
2301 // The caller is not allowed to change the data.
2302 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2303 // And we are resetting to find the next component...
2304 intent.setComponent(null);
2305
2306 ActivityInfo aInfo = null;
2307 try {
2308 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002309 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002310 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002311 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312
2313 // Look for the original activity in the list...
2314 final int N = resolves != null ? resolves.size() : 0;
2315 for (int i=0; i<N; i++) {
2316 ResolveInfo rInfo = resolves.get(i);
2317 if (rInfo.activityInfo.packageName.equals(r.packageName)
2318 && rInfo.activityInfo.name.equals(r.info.name)) {
2319 // We found the current one... the next matching is
2320 // after it.
2321 i++;
2322 if (i<N) {
2323 aInfo = resolves.get(i).activityInfo;
2324 }
2325 break;
2326 }
2327 }
2328 } catch (RemoteException e) {
2329 }
2330
2331 if (aInfo == null) {
2332 // Nobody who is next!
2333 return false;
2334 }
2335
2336 intent.setComponent(new ComponentName(
2337 aInfo.applicationInfo.packageName, aInfo.name));
2338 intent.setFlags(intent.getFlags()&~(
2339 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2340 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2341 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2342 Intent.FLAG_ACTIVITY_NEW_TASK));
2343
2344 // Okay now we need to start the new activity, replacing the
2345 // currently running activity. This is a little tricky because
2346 // we want to start the new one as if the current one is finished,
2347 // but not finish the current one first so that there is no flicker.
2348 // And thus...
2349 final boolean wasFinishing = r.finishing;
2350 r.finishing = true;
2351
2352 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002353 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 final String resultWho = r.resultWho;
2355 final int requestCode = r.requestCode;
2356 r.resultTo = null;
2357 if (resultTo != null) {
2358 resultTo.removeResultsLocked(r, resultWho, requestCode);
2359 }
2360
2361 final long origId = Binder.clearCallingIdentity();
2362 // XXX we are not dealing with propagating grantedUriPermissions...
2363 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002364 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002365 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002366 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 Binder.restoreCallingIdentity(origId);
2368
2369 r.finishing = wasFinishing;
2370 if (res != START_SUCCESS) {
2371 return false;
2372 }
2373 return true;
2374 }
2375 }
2376
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002377 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002378 Intent intent, String resolvedType, IBinder resultTo,
2379 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002380
2381 // This is so super not safe, that only the system (or okay root)
2382 // can do it.
2383 final int callingUid = Binder.getCallingUid();
2384 if (callingUid != 0 && callingUid != Process.myUid()) {
2385 throw new SecurityException(
2386 "startActivityInPackage only available to the system");
2387 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002388
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002389 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2390 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2391 }
2392
2393 public final int startActivities(IApplicationThread caller,
2394 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2395 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2396 }
2397
2398 public final int startActivitiesInPackage(int uid,
2399 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2400
2401 // This is so super not safe, that only the system (or okay root)
2402 // can do it.
2403 final int callingUid = Binder.getCallingUid();
2404 if (callingUid != 0 && callingUid != Process.myUid()) {
2405 throw new SecurityException(
2406 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002407 }
2408
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002409 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002410 }
2411
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002412 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002413 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002414 // Quick case: check if the top-most recent task is the same.
2415 if (N > 0 && mRecentTasks.get(0) == task) {
2416 return;
2417 }
2418 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002419 for (int i=0; i<N; i++) {
2420 TaskRecord tr = mRecentTasks.get(i);
2421 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2422 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2423 mRecentTasks.remove(i);
2424 i--;
2425 N--;
2426 if (task.intent == null) {
2427 // If the new recent task we are adding is not fully
2428 // specified, then replace it with the existing recent task.
2429 task = tr;
2430 }
2431 }
2432 }
2433 if (N >= MAX_RECENT_TASKS) {
2434 mRecentTasks.remove(N-1);
2435 }
2436 mRecentTasks.add(0, task);
2437 }
2438
2439 public void setRequestedOrientation(IBinder token,
2440 int requestedOrientation) {
2441 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002442 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002443 if (index < 0) {
2444 return;
2445 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002446 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002447 final long origId = Binder.clearCallingIdentity();
2448 mWindowManager.setAppOrientation(r, requestedOrientation);
2449 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002450 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002451 r.mayFreezeScreenLocked(r.app) ? r : null);
2452 if (config != null) {
2453 r.frozenBeforeDestroy = true;
2454 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002455 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002456 }
2457 }
2458 Binder.restoreCallingIdentity(origId);
2459 }
2460 }
2461
2462 public int getRequestedOrientation(IBinder token) {
2463 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002464 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002465 if (index < 0) {
2466 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2467 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002468 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002469 return mWindowManager.getAppOrientation(r);
2470 }
2471 }
2472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002473 /**
2474 * This is the internal entry point for handling Activity.finish().
2475 *
2476 * @param token The Binder token referencing the Activity we want to finish.
2477 * @param resultCode Result code, if any, from this Activity.
2478 * @param resultData Result data (Intent), if any, from this Activity.
2479 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002480 * @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 -08002481 */
2482 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2483 // Refuse possible leaked file descriptors
2484 if (resultData != null && resultData.hasFileDescriptors() == true) {
2485 throw new IllegalArgumentException("File descriptors passed in Intent");
2486 }
2487
2488 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002489 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002490 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002491 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492 if (next != null) {
2493 // ask watcher if this is allowed
2494 boolean resumeOK = true;
2495 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002496 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002497 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002498 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002499 }
2500
2501 if (!resumeOK) {
2502 return false;
2503 }
2504 }
2505 }
2506 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002507 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002508 resultData, "app-request");
2509 Binder.restoreCallingIdentity(origId);
2510 return res;
2511 }
2512 }
2513
Dianne Hackborn860755f2010-06-03 18:47:52 -07002514 public final void finishHeavyWeightApp() {
2515 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2516 != PackageManager.PERMISSION_GRANTED) {
2517 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2518 + Binder.getCallingPid()
2519 + ", uid=" + Binder.getCallingUid()
2520 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2521 Slog.w(TAG, msg);
2522 throw new SecurityException(msg);
2523 }
2524
2525 synchronized(this) {
2526 if (mHeavyWeightProcess == null) {
2527 return;
2528 }
2529
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002530 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002531 mHeavyWeightProcess.activities);
2532 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002533 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002534 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002535 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002536 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002537 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002538 null, "finish-heavy");
2539 }
2540 }
2541 }
2542
2543 mHeavyWeightProcess = null;
2544 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2545 }
2546 }
2547
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002548 public void crashApplication(int uid, int initialPid, String packageName,
2549 String message) {
2550 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2551 != PackageManager.PERMISSION_GRANTED) {
2552 String msg = "Permission Denial: crashApplication() from pid="
2553 + Binder.getCallingPid()
2554 + ", uid=" + Binder.getCallingUid()
2555 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2556 Slog.w(TAG, msg);
2557 throw new SecurityException(msg);
2558 }
2559
2560 synchronized(this) {
2561 ProcessRecord proc = null;
2562
2563 // Figure out which process to kill. We don't trust that initialPid
2564 // still has any relation to current pids, so must scan through the
2565 // list.
2566 synchronized (mPidsSelfLocked) {
2567 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2568 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2569 if (p.info.uid != uid) {
2570 continue;
2571 }
2572 if (p.pid == initialPid) {
2573 proc = p;
2574 break;
2575 }
2576 for (String str : p.pkgList) {
2577 if (str.equals(packageName)) {
2578 proc = p;
2579 }
2580 }
2581 }
2582 }
2583
2584 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002585 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002586 + " initialPid=" + initialPid
2587 + " packageName=" + packageName);
2588 return;
2589 }
2590
2591 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002592 if (proc.pid == Process.myPid()) {
2593 Log.w(TAG, "crashApplication: trying to crash self!");
2594 return;
2595 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002596 long ident = Binder.clearCallingIdentity();
2597 try {
2598 proc.thread.scheduleCrash(message);
2599 } catch (RemoteException e) {
2600 }
2601 Binder.restoreCallingIdentity(ident);
2602 }
2603 }
2604 }
2605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002606 public final void finishSubActivity(IBinder token, String resultWho,
2607 int requestCode) {
2608 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002609 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 if (index < 0) {
2611 return;
2612 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002613 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002614
2615 final long origId = Binder.clearCallingIdentity();
2616
2617 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002618 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2619 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620 if (r.resultTo == self && r.requestCode == requestCode) {
2621 if ((r.resultWho == null && resultWho == null) ||
2622 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002623 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 Activity.RESULT_CANCELED, null, "request-sub");
2625 }
2626 }
2627 }
2628
2629 Binder.restoreCallingIdentity(origId);
2630 }
2631 }
2632
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002633 public boolean willActivityBeVisible(IBinder token) {
2634 synchronized(this) {
2635 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002636 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2637 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002638 if (r == token) {
2639 return true;
2640 }
2641 if (r.fullscreen && !r.finishing) {
2642 return false;
2643 }
2644 }
2645 return true;
2646 }
2647 }
2648
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002649 public void overridePendingTransition(IBinder token, String packageName,
2650 int enterAnim, int exitAnim) {
2651 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002652 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002653 if (index < 0) {
2654 return;
2655 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002656 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002657
2658 final long origId = Binder.clearCallingIdentity();
2659
2660 if (self.state == ActivityState.RESUMED
2661 || self.state == ActivityState.PAUSING) {
2662 mWindowManager.overridePendingAppTransition(packageName,
2663 enterAnim, exitAnim);
2664 }
2665
2666 Binder.restoreCallingIdentity(origId);
2667 }
2668 }
2669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002670 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 * Main function for removing an existing process from the activity manager
2672 * as a result of that process going away. Clears out all connections
2673 * to the process.
2674 */
2675 private final void handleAppDiedLocked(ProcessRecord app,
2676 boolean restarting) {
2677 cleanUpApplicationRecordLocked(app, restarting, -1);
2678 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002679 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680 }
2681
2682 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002683 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2684 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2685 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002686 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002687 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2688 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 }
2690
2691 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002692 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693
2694 boolean atTop = true;
2695 boolean hasVisibleActivities = false;
2696
2697 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002698 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002699 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002700 TAG, "Removing app " + app + " from history with " + i + " entries");
2701 while (i > 0) {
2702 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002703 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002704 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2706 if (r.app == app) {
2707 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002708 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002709 TAG, "Removing this entry! frozen=" + r.haveState
2710 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002711 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002712 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002713 r.takeFromHistory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 mWindowManager.removeAppToken(r);
2715 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002716 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002718 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719
2720 } else {
2721 // We have the current state for this activity, so
2722 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002723 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002724 TAG, "Keeping entry, setting app to null");
2725 if (r.visible) {
2726 hasVisibleActivities = true;
2727 }
2728 r.app = null;
2729 r.nowVisible = false;
2730 if (!r.haveState) {
2731 r.icicle = null;
2732 }
2733 }
2734
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002735 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002736 r.state = ActivityState.STOPPED;
2737 }
2738 atTop = false;
2739 }
2740
2741 app.activities.clear();
2742
2743 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002744 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 + " running instrumentation " + app.instrumentationClass);
2746 Bundle info = new Bundle();
2747 info.putString("shortMsg", "Process crashed.");
2748 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2749 }
2750
2751 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002752 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002753 // If there was nothing to resume, and we are not already
2754 // restarting this process, but there is a visible activity that
2755 // is hosted by the process... then make sure all visible
2756 // activities are running, taking care of restarting this
2757 // process.
2758 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002759 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002760 }
2761 }
2762 }
2763 }
2764
2765 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2766 IBinder threadBinder = thread.asBinder();
2767
2768 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002769 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2770 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002771 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2772 return i;
2773 }
2774 }
2775 return -1;
2776 }
2777
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002778 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 IApplicationThread thread) {
2780 if (thread == null) {
2781 return null;
2782 }
2783
2784 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002785 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 }
2787
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002788 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002789 IApplicationThread thread) {
2790
2791 mProcDeaths[0]++;
2792
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002793 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2794 synchronized (stats) {
2795 stats.noteProcessDiedLocked(app.info.uid, pid);
2796 }
2797
Magnus Edlund7bb25812010-02-24 15:45:06 +01002798 // Clean up already done if the process has been re-started.
2799 if (app.pid == pid && app.thread != null &&
2800 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002801 if (!app.killedBackground) {
2802 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2803 + ") has died.");
2804 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002805 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002806 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002807 TAG, "Dying app: " + app + ", pid: " + pid
2808 + ", thread: " + thread.asBinder());
2809 boolean doLowMem = app.instrumentationClass == null;
2810 handleAppDiedLocked(app, false);
2811
2812 if (doLowMem) {
2813 // If there are no longer any background processes running,
2814 // and the app that died was not running instrumentation,
2815 // then tell everyone we are now low on memory.
2816 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002817 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2818 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002819 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2820 haveBg = true;
2821 break;
2822 }
2823 }
2824
2825 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002826 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002827 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002828 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002829 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2830 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002831 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002832 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2833 // The low memory report is overriding any current
2834 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002835 // heavy/important/visible/foreground processes first.
2836 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002837 rec.lastRequestedGc = 0;
2838 } else {
2839 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002840 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002841 rec.reportLowMemory = true;
2842 rec.lastLowMemory = now;
2843 mProcessesToGc.remove(rec);
2844 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002845 }
2846 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002847 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 }
2849 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002850 } else if (app.pid != pid) {
2851 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002852 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002853 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002854 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002855 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002856 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002857 + thread.asBinder());
2858 }
2859 }
2860
Dan Egnor42471dd2010-01-07 17:25:22 -08002861 /**
2862 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002863 * @param clearTraces causes the dump file to be erased prior to the new
2864 * traces being written, if true; when false, the new traces will be
2865 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002866 * @param firstPids of dalvik VM processes to dump stack traces for first
2867 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002868 * @return file containing stack traces, or null if no dump file is configured
2869 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002870 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2871 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002872 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2873 if (tracesPath == null || tracesPath.length() == 0) {
2874 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002875 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002876
2877 File tracesFile = new File(tracesPath);
2878 try {
2879 File tracesDir = tracesFile.getParentFile();
2880 if (!tracesDir.exists()) tracesFile.mkdirs();
2881 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2882
Christopher Tate6ee412d2010-05-28 12:01:56 -07002883 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002884 tracesFile.createNewFile();
2885 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2886 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002887 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002888 return null;
2889 }
2890
2891 // Use a FileObserver to detect when traces finish writing.
2892 // The order of traces is considered important to maintain for legibility.
2893 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2894 public synchronized void onEvent(int event, String path) { notify(); }
2895 };
2896
2897 try {
2898 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002899
2900 // First collect all of the stacks of the most important pids.
2901 try {
2902 int num = firstPids.size();
2903 for (int i = 0; i < num; i++) {
2904 synchronized (observer) {
2905 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2906 observer.wait(200); // Wait for write-close, give up after 200msec
2907 }
2908 }
2909 } catch (InterruptedException e) {
2910 Log.wtf(TAG, e);
2911 }
2912
2913 // Next measure CPU usage.
2914 if (processStats != null) {
2915 processStats.init();
2916 System.gc();
2917 processStats.update();
2918 try {
2919 synchronized (processStats) {
2920 processStats.wait(500); // measure over 1/2 second.
2921 }
2922 } catch (InterruptedException e) {
2923 }
2924 processStats.update();
2925
2926 // We'll take the stack crawls of just the top apps using CPU.
2927 final int N = processStats.countWorkingStats();
2928 int numProcs = 0;
2929 for (int i=0; i<N && numProcs<5; i++) {
2930 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2931 if (lastPids.indexOfKey(stats.pid) >= 0) {
2932 numProcs++;
2933 try {
2934 synchronized (observer) {
2935 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2936 observer.wait(200); // Wait for write-close, give up after 200msec
2937 }
2938 } catch (InterruptedException e) {
2939 Log.wtf(TAG, e);
2940 }
2941
2942 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002943 }
2944 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002945
2946 return tracesFile;
2947
Dan Egnor42471dd2010-01-07 17:25:22 -08002948 } finally {
2949 observer.stopWatching();
2950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 }
2952
Jeff Brown4d94a762010-09-23 11:33:28 -07002953 private final class AppNotResponding implements Runnable {
2954 private final ProcessRecord mApp;
2955 private final String mAnnotation;
2956
2957 public AppNotResponding(ProcessRecord app, String annotation) {
2958 mApp = app;
2959 mAnnotation = annotation;
2960 }
2961
2962 @Override
2963 public void run() {
2964 appNotResponding(mApp, null, null, mAnnotation);
2965 }
2966 }
2967
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002968 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2969 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002970 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2971 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2972
Dianne Hackborn287952c2010-09-22 22:34:31 -07002973 if (mController != null) {
2974 try {
2975 // 0 == continue, -1 = kill process immediately
2976 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2977 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2978 } catch (RemoteException e) {
2979 mController = null;
2980 }
2981 }
2982
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002983 long anrTime = SystemClock.uptimeMillis();
2984 if (MONITOR_CPU_USAGE) {
2985 updateCpuStatsNow();
2986 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002987
2988 synchronized (this) {
2989 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2990 if (mShuttingDown) {
2991 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2992 return;
2993 } else if (app.notResponding) {
2994 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2995 return;
2996 } else if (app.crashing) {
2997 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2998 return;
2999 }
3000
3001 // In case we come through here for the same app before completing
3002 // this one, mark as anring now so we will bail out.
3003 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08003004
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003005 // Log the ANR to the event log.
3006 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
3007 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08003008
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003009 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003010 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003011
3012 int parentPid = app.pid;
3013 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003014 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003015
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003016 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08003017
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003018 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
3019 ProcessRecord r = mLruProcesses.get(i);
3020 if (r != null && r.thread != null) {
3021 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003022 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
3023 if (r.persistent) {
3024 firstPids.add(pid);
3025 } else {
3026 lastPids.put(pid, Boolean.TRUE);
3027 }
3028 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003029 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003030 }
3031 }
3032
Dan Egnor42471dd2010-01-07 17:25:22 -08003033 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003034 StringBuilder info = mStringBuilder;
3035 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08003036 info.append("ANR in ").append(app.processName);
3037 if (activity != null && activity.shortComponentName != null) {
3038 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07003039 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08003040 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003042 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003044 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003045 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047
Dianne Hackborn287952c2010-09-22 22:34:31 -07003048 final ProcessStats processStats = new ProcessStats(true);
3049
3050 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
3051
Dan Egnor42471dd2010-01-07 17:25:22 -08003052 String cpuInfo = null;
3053 if (MONITOR_CPU_USAGE) {
3054 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003055 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003056 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003057 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003058 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08003059 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003060 }
3061
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003062 info.append(processStats.printCurrentState(anrTime));
3063
Joe Onorato8a9b2202010-02-26 18:56:32 -08003064 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08003065 if (tracesFile == null) {
3066 // There is no trace file, so dump (only) the alleged culprit's threads to the log
3067 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
3068 }
3069
3070 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
3071
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003072 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003073 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08003074 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
3075 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003076 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003077 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3078 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003079 }
3080 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003081 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 }
3083 }
3084
Dan Egnor42471dd2010-01-07 17:25:22 -08003085 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
3086 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
3087 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003088
3089 synchronized (this) {
3090 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003091 Slog.w(TAG, "Killing " + app + ": background ANR");
3092 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
3093 app.processName, app.setAdj, "background ANR");
3094 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003095 return;
3096 }
3097
3098 // Set the app's notResponding state, and look up the errorReportReceiver
3099 makeAppNotRespondingLocked(app,
3100 activity != null ? activity.shortComponentName : null,
3101 annotation != null ? "ANR " + annotation : "ANR",
3102 info.toString());
3103
3104 // Bring up the infamous App Not Responding dialog
3105 Message msg = Message.obtain();
3106 HashMap map = new HashMap();
3107 msg.what = SHOW_NOT_RESPONDING_MSG;
3108 msg.obj = map;
3109 map.put("app", app);
3110 if (activity != null) {
3111 map.put("activity", activity);
3112 }
3113
3114 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003116 }
3117
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003118 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3119 if (!mLaunchWarningShown) {
3120 mLaunchWarningShown = true;
3121 mHandler.post(new Runnable() {
3122 @Override
3123 public void run() {
3124 synchronized (ActivityManagerService.this) {
3125 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3126 d.show();
3127 mHandler.postDelayed(new Runnable() {
3128 @Override
3129 public void run() {
3130 synchronized (ActivityManagerService.this) {
3131 d.dismiss();
3132 mLaunchWarningShown = false;
3133 }
3134 }
3135 }, 4000);
3136 }
3137 }
3138 });
3139 }
3140 }
3141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 public boolean clearApplicationUserData(final String packageName,
3143 final IPackageDataObserver observer) {
3144 int uid = Binder.getCallingUid();
3145 int pid = Binder.getCallingPid();
3146 long callingId = Binder.clearCallingIdentity();
3147 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003148 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003149 int pkgUid = -1;
3150 synchronized(this) {
3151 try {
3152 pkgUid = pm.getPackageUid(packageName);
3153 } catch (RemoteException e) {
3154 }
3155 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003156 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 return false;
3158 }
3159 if (uid == pkgUid || checkComponentPermission(
3160 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003161 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003163 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003164 } else {
3165 throw new SecurityException(pid+" does not have permission:"+
3166 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3167 "for process:"+packageName);
3168 }
3169 }
3170
3171 try {
3172 //clear application user data
3173 pm.clearApplicationUserData(packageName, observer);
3174 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3175 Uri.fromParts("package", packageName, null));
3176 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003177 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3178 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003179 } catch (RemoteException e) {
3180 }
3181 } finally {
3182 Binder.restoreCallingIdentity(callingId);
3183 }
3184 return true;
3185 }
3186
Dianne Hackborn03abb812010-01-04 18:43:19 -08003187 public void killBackgroundProcesses(final String packageName) {
3188 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3189 != PackageManager.PERMISSION_GRANTED &&
3190 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3191 != PackageManager.PERMISSION_GRANTED) {
3192 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003193 + Binder.getCallingPid()
3194 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003195 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003196 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003197 throw new SecurityException(msg);
3198 }
3199
3200 long callingId = Binder.clearCallingIdentity();
3201 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003202 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003203 int pkgUid = -1;
3204 synchronized(this) {
3205 try {
3206 pkgUid = pm.getPackageUid(packageName);
3207 } catch (RemoteException e) {
3208 }
3209 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003210 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003211 return;
3212 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003213 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003214 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003215 }
3216 } finally {
3217 Binder.restoreCallingIdentity(callingId);
3218 }
3219 }
3220
3221 public void forceStopPackage(final String packageName) {
3222 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3223 != PackageManager.PERMISSION_GRANTED) {
3224 String msg = "Permission Denial: forceStopPackage() from pid="
3225 + Binder.getCallingPid()
3226 + ", uid=" + Binder.getCallingUid()
3227 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003228 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003229 throw new SecurityException(msg);
3230 }
3231
3232 long callingId = Binder.clearCallingIdentity();
3233 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003234 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003235 int pkgUid = -1;
3236 synchronized(this) {
3237 try {
3238 pkgUid = pm.getPackageUid(packageName);
3239 } catch (RemoteException e) {
3240 }
3241 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003242 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003243 return;
3244 }
3245 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003246 try {
3247 pm.setPackageStoppedState(packageName, true);
3248 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003249 } catch (IllegalArgumentException e) {
3250 Slog.w(TAG, "Failed trying to unstop package "
3251 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 }
3254 } finally {
3255 Binder.restoreCallingIdentity(callingId);
3256 }
3257 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003258
3259 /*
3260 * The pkg name and uid have to be specified.
3261 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3262 */
3263 public void killApplicationWithUid(String pkg, int uid) {
3264 if (pkg == null) {
3265 return;
3266 }
3267 // Make sure the uid is valid.
3268 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003269 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003270 return;
3271 }
3272 int callerUid = Binder.getCallingUid();
3273 // Only the system server can kill an application
3274 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003275 // Post an aysnc message to kill the application
3276 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3277 msg.arg1 = uid;
3278 msg.arg2 = 0;
3279 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003280 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003281 } else {
3282 throw new SecurityException(callerUid + " cannot kill pkg: " +
3283 pkg);
3284 }
3285 }
3286
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003287 public void closeSystemDialogs(String reason) {
3288 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003289 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003290 if (reason != null) {
3291 intent.putExtra("reason", reason);
3292 }
3293
3294 final int uid = Binder.getCallingUid();
3295 final long origId = Binder.clearCallingIdentity();
3296 synchronized (this) {
3297 int i = mWatchers.beginBroadcast();
3298 while (i > 0) {
3299 i--;
3300 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3301 if (w != null) {
3302 try {
3303 w.closingSystemDialogs(reason);
3304 } catch (RemoteException e) {
3305 }
3306 }
3307 }
3308 mWatchers.finishBroadcast();
3309
Dianne Hackbornffa42482009-09-23 22:20:11 -07003310 mWindowManager.closeSystemDialogs(reason);
3311
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003312 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3313 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003314 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003315 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003316 Activity.RESULT_CANCELED, null, "close-sys");
3317 }
3318 }
3319
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003320 broadcastIntentLocked(null, null, intent, null,
3321 null, 0, null, null, null, false, false, -1, uid);
3322 }
3323 Binder.restoreCallingIdentity(origId);
3324 }
3325
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003326 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003327 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003328 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3329 for (int i=pids.length-1; i>=0; i--) {
3330 infos[i] = new Debug.MemoryInfo();
3331 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003332 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003333 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003334 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003335
3336 public void killApplicationProcess(String processName, int uid) {
3337 if (processName == null) {
3338 return;
3339 }
3340
3341 int callerUid = Binder.getCallingUid();
3342 // Only the system server can kill an application
3343 if (callerUid == Process.SYSTEM_UID) {
3344 synchronized (this) {
3345 ProcessRecord app = getProcessRecordLocked(processName, uid);
Christopher Tate4a627c72011-04-01 14:43:32 -07003346 if (app != null && app.thread != null) {
Christopher Tate5e1ab332009-09-01 20:32:49 -07003347 try {
3348 app.thread.scheduleSuicide();
3349 } catch (RemoteException e) {
3350 // If the other end already died, then our work here is done.
3351 }
3352 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003353 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003354 + processName + " / " + uid);
3355 }
3356 }
3357 } else {
3358 throw new SecurityException(callerUid + " cannot kill app process: " +
3359 processName);
3360 }
3361 }
3362
Dianne Hackborn03abb812010-01-04 18:43:19 -08003363 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003364 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3366 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003367 if (!mProcessesReady) {
3368 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 intent.putExtra(Intent.EXTRA_UID, uid);
3371 broadcastIntentLocked(null, null, intent,
3372 null, null, 0, null, null, null,
3373 false, false, MY_PID, Process.SYSTEM_UID);
3374 }
3375
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003376 private final boolean killPackageProcessesLocked(String packageName, int uid,
3377 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003378 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379
Dianne Hackborn03abb812010-01-04 18:43:19 -08003380 // Remove all processes this package may have touched: all with the
3381 // same UID (except for the system or root user), and all whose name
3382 // matches the package name.
3383 final String procNamePrefix = packageName + ":";
3384 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3385 final int NA = apps.size();
3386 for (int ia=0; ia<NA; ia++) {
3387 ProcessRecord app = apps.valueAt(ia);
3388 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003389 if (doit) {
3390 procs.add(app);
3391 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003392 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3393 || app.processName.equals(packageName)
3394 || app.processName.startsWith(procNamePrefix)) {
3395 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003396 if (!doit) {
3397 return true;
3398 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003399 app.removed = true;
3400 procs.add(app);
3401 }
3402 }
3403 }
3404 }
3405
3406 int N = procs.size();
3407 for (int i=0; i<N; i++) {
3408 removeProcessLocked(procs.get(i), callerWillRestart);
3409 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003410 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003411 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003412
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003413 private final boolean forceStopPackageLocked(String name, int uid,
3414 boolean callerWillRestart, boolean purgeCache, boolean doit) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07003415 int i;
3416 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003418 if (uid < 0) {
3419 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003420 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003421 } catch (RemoteException e) {
3422 }
3423 }
3424
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003425 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003426 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003427
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003428 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3429 while (badApps.hasNext()) {
3430 SparseArray<Long> ba = badApps.next();
3431 if (ba.get(uid) != null) {
3432 badApps.remove();
3433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 }
3435 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003436
3437 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3438 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003439
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003440 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3441 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003442 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003443 if (!doit) {
3444 return true;
3445 }
3446 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003447 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 if (r.app != null) {
3449 r.app.removed = true;
3450 }
3451 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003452 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 }
3454 }
3455
3456 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3457 for (ServiceRecord service : mServices.values()) {
3458 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003459 if (!doit) {
3460 return true;
3461 }
3462 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003463 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 if (service.app != null) {
3465 service.app.removed = true;
3466 }
3467 service.app = null;
3468 services.add(service);
3469 }
3470 }
3471
3472 N = services.size();
3473 for (i=0; i<N; i++) {
3474 bringDownServiceLocked(services.get(i), true);
3475 }
3476
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003477 if (doit) {
3478 if (purgeCache) {
3479 AttributeCache ac = AttributeCache.instance();
3480 if (ac != null) {
3481 ac.removePackage(name);
3482 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003483 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003484 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003485 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003486
3487 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 }
3489
3490 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3491 final String name = app.processName;
3492 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003493 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494 TAG, "Force removing process " + app + " (" + name
3495 + "/" + uid + ")");
3496
3497 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003498 if (mHeavyWeightProcess == app) {
3499 mHeavyWeightProcess = null;
3500 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 boolean needRestart = false;
3503 if (app.pid > 0 && app.pid != MY_PID) {
3504 int pid = app.pid;
3505 synchronized (mPidsSelfLocked) {
3506 mPidsSelfLocked.remove(pid);
3507 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3508 }
3509 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003510 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003511 Process.killProcess(pid);
3512
3513 if (app.persistent) {
3514 if (!callerWillRestart) {
3515 addAppLocked(app.info);
3516 } else {
3517 needRestart = true;
3518 }
3519 }
3520 } else {
3521 mRemovedProcesses.add(app);
3522 }
3523
3524 return needRestart;
3525 }
3526
3527 private final void processStartTimedOutLocked(ProcessRecord app) {
3528 final int pid = app.pid;
3529 boolean gone = false;
3530 synchronized (mPidsSelfLocked) {
3531 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3532 if (knownApp != null && knownApp.thread == null) {
3533 mPidsSelfLocked.remove(pid);
3534 gone = true;
3535 }
3536 }
3537
3538 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003539 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003540 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003541 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003543 if (mHeavyWeightProcess == app) {
3544 mHeavyWeightProcess = null;
3545 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3546 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003547 // Take care of any launching providers waiting for this process.
3548 checkAppInLaunchingProvidersLocked(app, true);
3549 // Take care of any services that are waiting for the process.
3550 for (int i=0; i<mPendingServices.size(); i++) {
3551 ServiceRecord sr = mPendingServices.get(i);
3552 if (app.info.uid == sr.appInfo.uid
3553 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003554 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003555 mPendingServices.remove(i);
3556 i--;
3557 bringDownServiceLocked(sr, true);
3558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003560 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
3561 app.processName, app.setAdj, "start timeout");
3562 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003563 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003564 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003565 try {
3566 IBackupManager bm = IBackupManager.Stub.asInterface(
3567 ServiceManager.getService(Context.BACKUP_SERVICE));
3568 bm.agentDisconnected(app.info.packageName);
3569 } catch (RemoteException e) {
3570 // Can't happen; the backup manager is local
3571 }
3572 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003573 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003574 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003575 mPendingBroadcast.state = BroadcastRecord.IDLE;
3576 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003577 mPendingBroadcast = null;
3578 scheduleBroadcastsLocked();
3579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003581 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 }
3583 }
3584
3585 private final boolean attachApplicationLocked(IApplicationThread thread,
3586 int pid) {
3587
3588 // Find the application record that is being attached... either via
3589 // the pid if we are running in multiple processes, or just pull the
3590 // next app record if we are emulating process with anonymous threads.
3591 ProcessRecord app;
3592 if (pid != MY_PID && pid >= 0) {
3593 synchronized (mPidsSelfLocked) {
3594 app = mPidsSelfLocked.get(pid);
3595 }
3596 } else if (mStartingProcesses.size() > 0) {
3597 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003598 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 } else {
3600 app = null;
3601 }
3602
3603 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003604 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003606 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003608 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 } else {
3610 try {
3611 thread.scheduleExit();
3612 } catch (Exception e) {
3613 // Ignore exceptions.
3614 }
3615 }
3616 return false;
3617 }
3618
3619 // If this application record is still attached to a previous
3620 // process, clean it up now.
3621 if (app.thread != null) {
3622 handleAppDiedLocked(app, true);
3623 }
3624
3625 // Tell the process all about itself.
3626
Joe Onorato8a9b2202010-02-26 18:56:32 -08003627 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 TAG, "Binding process pid " + pid + " to record " + app);
3629
3630 String processName = app.processName;
3631 try {
3632 thread.asBinder().linkToDeath(new AppDeathRecipient(
3633 app, pid, thread), 0);
3634 } catch (RemoteException e) {
3635 app.resetPackageList();
3636 startProcessLocked(app, "link fail", processName);
3637 return false;
3638 }
3639
Doug Zongker2bec3d42009-12-04 12:52:44 -08003640 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641
3642 app.thread = thread;
3643 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003644 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3645 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003646 app.forcingToForeground = null;
3647 app.foregroundServices = false;
3648 app.debugging = false;
3649
3650 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3651
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003652 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003653 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003654
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003655 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003656 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003657 }
3658
Joe Onorato8a9b2202010-02-26 18:56:32 -08003659 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 TAG, "New app record " + app
3661 + " thread=" + thread.asBinder() + " pid=" + pid);
3662 try {
3663 int testMode = IApplicationThread.DEBUG_OFF;
3664 if (mDebugApp != null && mDebugApp.equals(processName)) {
3665 testMode = mWaitForDebugger
3666 ? IApplicationThread.DEBUG_WAIT
3667 : IApplicationThread.DEBUG_ON;
3668 app.debugging = true;
3669 if (mDebugTransient) {
3670 mDebugApp = mOrigDebugApp;
3671 mWaitForDebugger = mOrigWaitForDebugger;
3672 }
3673 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003674
Christopher Tate181fafa2009-05-14 11:12:14 -07003675 // If the app is being launched for restore or full backup, set it up specially
3676 boolean isRestrictedBackupMode = false;
3677 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3678 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07003679 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07003680 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3681 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003682
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003683 ensurePackageDexOpt(app.instrumentationInfo != null
3684 ? app.instrumentationInfo.packageName
3685 : app.info.packageName);
3686 if (app.instrumentationClass != null) {
3687 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003688 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003689 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003690 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003691 ApplicationInfo appInfo = app.instrumentationInfo != null
3692 ? app.instrumentationInfo : app.info;
3693 thread.bindApplication(processName, appInfo, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 app.instrumentationClass, app.instrumentationProfileFile,
3695 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003696 isRestrictedBackupMode || !normalMode,
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003697 mConfiguration, compatibilityInfoForPackageLocked(appInfo),
3698 getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003699 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003700 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003701 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003702 } catch (Exception e) {
3703 // todo: Yikes! What should we do? For now we will try to
3704 // start another process, but that could easily get us in
3705 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003706 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003707
3708 app.resetPackageList();
3709 startProcessLocked(app, "bind fail", processName);
3710 return false;
3711 }
3712
3713 // Remove this record from the list of starting applications.
3714 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003715 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3716 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003717 mProcessesOnHold.remove(app);
3718
3719 boolean badApp = false;
3720 boolean didSomething = false;
3721
3722 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003723 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003724 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003725 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3726 && processName.equals(hr.processName)) {
3727 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003728 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 didSomething = true;
3730 }
3731 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003732 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003733 + hr.intent.getComponent().flattenToShortString(), e);
3734 badApp = true;
3735 }
3736 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003737 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003738 }
3739 }
3740
3741 // Find any services that should be running in this process...
3742 if (!badApp && mPendingServices.size() > 0) {
3743 ServiceRecord sr = null;
3744 try {
3745 for (int i=0; i<mPendingServices.size(); i++) {
3746 sr = mPendingServices.get(i);
3747 if (app.info.uid != sr.appInfo.uid
3748 || !processName.equals(sr.processName)) {
3749 continue;
3750 }
3751
3752 mPendingServices.remove(i);
3753 i--;
3754 realStartServiceLocked(sr, app);
3755 didSomething = true;
3756 }
3757 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003758 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003759 + sr.shortName, e);
3760 badApp = true;
3761 }
3762 }
3763
3764 // Check if the next broadcast receiver is in this process...
3765 BroadcastRecord br = mPendingBroadcast;
3766 if (!badApp && br != null && br.curApp == app) {
3767 try {
3768 mPendingBroadcast = null;
3769 processCurBroadcastLocked(br, app);
3770 didSomething = true;
3771 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003772 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 + br.curComponent.flattenToShortString(), e);
3774 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003775 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3777 br.resultExtras, br.resultAbort, true);
3778 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003779 // We need to reset the state if we fails to start the receiver.
3780 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003781 }
3782 }
3783
Christopher Tate181fafa2009-05-14 11:12:14 -07003784 // Check whether the next backup agent is in this process...
3785 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003786 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003787 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003788 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003789 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
3790 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
3791 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07003792 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003793 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003794 e.printStackTrace();
3795 }
3796 }
3797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 if (badApp) {
3799 // todo: Also need to kill application to deal with all
3800 // kinds of exceptions.
3801 handleAppDiedLocked(app, false);
3802 return false;
3803 }
3804
3805 if (!didSomething) {
3806 updateOomAdjLocked();
3807 }
3808
3809 return true;
3810 }
3811
3812 public final void attachApplication(IApplicationThread thread) {
3813 synchronized (this) {
3814 int callingPid = Binder.getCallingPid();
3815 final long origId = Binder.clearCallingIdentity();
3816 attachApplicationLocked(thread, callingPid);
3817 Binder.restoreCallingIdentity(origId);
3818 }
3819 }
3820
Dianne Hackborne88846e2009-09-30 21:34:25 -07003821 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003822 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003823 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 Binder.restoreCallingIdentity(origId);
3825 }
3826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003828 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003829 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 mWindowManager.enableScreenAfterBoot();
3831 }
3832
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003833 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003834 IntentFilter pkgFilter = new IntentFilter();
3835 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3836 pkgFilter.addDataScheme("package");
3837 mContext.registerReceiver(new BroadcastReceiver() {
3838 @Override
3839 public void onReceive(Context context, Intent intent) {
3840 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3841 if (pkgs != null) {
3842 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003843 synchronized (ActivityManagerService.this) {
3844 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3845 setResultCode(Activity.RESULT_OK);
3846 return;
3847 }
3848 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003849 }
3850 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003851 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003852 }, pkgFilter);
3853
3854 synchronized (this) {
3855 // Ensure that any processes we had put on hold are now started
3856 // up.
3857 final int NP = mProcessesOnHold.size();
3858 if (NP > 0) {
3859 ArrayList<ProcessRecord> procs =
3860 new ArrayList<ProcessRecord>(mProcessesOnHold);
3861 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003862 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3863 + procs.get(ip));
3864 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003865 }
3866 }
3867
3868 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003869 // Start looking for apps that are abusing wake locks.
3870 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003871 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003872 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003873 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003874 broadcastIntentLocked(null, null,
3875 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3876 null, null, 0, null, null,
3877 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3878 false, false, MY_PID, Process.SYSTEM_UID);
3879 }
3880 }
3881 }
3882
3883 final void ensureBootCompleted() {
3884 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003885 boolean enableScreen;
3886 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003887 booting = mBooting;
3888 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003889 enableScreen = !mBooted;
3890 mBooted = true;
3891 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003892
3893 if (booting) {
3894 finishBooting();
3895 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003896
3897 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003898 enableScreenAfterBoot();
3899 }
3900 }
3901
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003902 public final void activityPaused(IBinder token) {
3903 final long origId = Binder.clearCallingIdentity();
3904 mMainStack.activityPaused(token, false);
3905 Binder.restoreCallingIdentity(origId);
3906 }
3907
3908 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3909 CharSequence description) {
3910 if (localLOGV) Slog.v(
3911 TAG, "Activity stopped: token=" + token);
3912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 // Refuse possible leaked file descriptors
3914 if (icicle != null && icicle.hasFileDescriptors()) {
3915 throw new IllegalArgumentException("File descriptors passed in Bundle");
3916 }
3917
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003918 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003919
3920 final long origId = Binder.clearCallingIdentity();
3921
3922 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003923 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003924 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003925 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003926 r.icicle = icicle;
3927 r.haveState = true;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003928 r.updateThumbnail(thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 r.stopped = true;
3930 r.state = ActivityState.STOPPED;
3931 if (!r.finishing) {
3932 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003933 r.stack.destroyActivityLocked(r, true);
3934 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 }
3936 }
3937 }
3938 }
3939
3940 if (r != null) {
3941 sendPendingThumbnail(r, null, null, null, false);
3942 }
3943
3944 trimApplications();
3945
3946 Binder.restoreCallingIdentity(origId);
3947 }
3948
3949 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003950 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003951 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 }
3953
3954 public String getCallingPackage(IBinder token) {
3955 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003956 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003957 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003958 }
3959 }
3960
3961 public ComponentName getCallingActivity(IBinder token) {
3962 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003963 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 return r != null ? r.intent.getComponent() : null;
3965 }
3966 }
3967
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003968 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003969 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003970 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003971 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972 if (r != null) {
3973 return r.resultTo;
3974 }
3975 }
3976 return null;
3977 }
3978
3979 public ComponentName getActivityClassForToken(IBinder token) {
3980 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003981 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003982 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003983 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003984 return r.intent.getComponent();
3985 }
3986 return null;
3987 }
3988 }
3989
3990 public String getPackageForToken(IBinder token) {
3991 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003992 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003994 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 return r.packageName;
3996 }
3997 return null;
3998 }
3999 }
4000
4001 public IIntentSender getIntentSender(int type,
4002 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004003 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004005 if (intents != null) {
4006 if (intents.length < 1) {
4007 throw new IllegalArgumentException("Intents array length must be >= 1");
4008 }
4009 for (int i=0; i<intents.length; i++) {
4010 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07004011 if (intent != null) {
4012 if (intent.hasFileDescriptors()) {
4013 throw new IllegalArgumentException("File descriptors passed in Intent");
4014 }
4015 if (type == INTENT_SENDER_BROADCAST &&
4016 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
4017 throw new IllegalArgumentException(
4018 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
4019 }
4020 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004021 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004022 }
4023 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004024 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004025 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004026 }
4027 }
4028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004029 synchronized(this) {
4030 int callingUid = Binder.getCallingUid();
4031 try {
4032 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
4033 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004034 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004035 .getPackageUid(packageName);
4036 if (uid != Binder.getCallingUid()) {
4037 String msg = "Permission Denial: getIntentSender() from pid="
4038 + Binder.getCallingPid()
4039 + ", uid=" + Binder.getCallingUid()
4040 + ", (need uid=" + uid + ")"
4041 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004042 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004043 throw new SecurityException(msg);
4044 }
4045 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004046
4047 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004048 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004050 } catch (RemoteException e) {
4051 throw new SecurityException(e);
4052 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004053 }
4054 }
4055
4056 IIntentSender getIntentSenderLocked(int type,
4057 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004058 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004059 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004060 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004061 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004062 if (index < 0) {
4063 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004064 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004065 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004066 if (activity.finishing) {
4067 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004068 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004069 }
4070
4071 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4072 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4073 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4074 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4075 |PendingIntent.FLAG_UPDATE_CURRENT);
4076
4077 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4078 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004079 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004080 WeakReference<PendingIntentRecord> ref;
4081 ref = mIntentSenderRecords.get(key);
4082 PendingIntentRecord rec = ref != null ? ref.get() : null;
4083 if (rec != null) {
4084 if (!cancelCurrent) {
4085 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004086 if (rec.key.requestIntent != null) {
4087 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4088 }
4089 if (intents != null) {
4090 intents[intents.length-1] = rec.key.requestIntent;
4091 rec.key.allIntents = intents;
4092 rec.key.allResolvedTypes = resolvedTypes;
4093 } else {
4094 rec.key.allIntents = null;
4095 rec.key.allResolvedTypes = null;
4096 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 return rec;
4099 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004100 rec.canceled = true;
4101 mIntentSenderRecords.remove(key);
4102 }
4103 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 return rec;
4105 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004106 rec = new PendingIntentRecord(this, key, callingUid);
4107 mIntentSenderRecords.put(key, rec.ref);
4108 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4109 if (activity.pendingResults == null) {
4110 activity.pendingResults
4111 = new HashSet<WeakReference<PendingIntentRecord>>();
4112 }
4113 activity.pendingResults.add(rec.ref);
4114 }
4115 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 }
4117
4118 public void cancelIntentSender(IIntentSender sender) {
4119 if (!(sender instanceof PendingIntentRecord)) {
4120 return;
4121 }
4122 synchronized(this) {
4123 PendingIntentRecord rec = (PendingIntentRecord)sender;
4124 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004125 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004126 .getPackageUid(rec.key.packageName);
4127 if (uid != Binder.getCallingUid()) {
4128 String msg = "Permission Denial: cancelIntentSender() from pid="
4129 + Binder.getCallingPid()
4130 + ", uid=" + Binder.getCallingUid()
4131 + " is not allowed to cancel packges "
4132 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004133 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004134 throw new SecurityException(msg);
4135 }
4136 } catch (RemoteException e) {
4137 throw new SecurityException(e);
4138 }
4139 cancelIntentSenderLocked(rec, true);
4140 }
4141 }
4142
4143 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4144 rec.canceled = true;
4145 mIntentSenderRecords.remove(rec.key);
4146 if (cleanActivity && rec.key.activity != null) {
4147 rec.key.activity.pendingResults.remove(rec.ref);
4148 }
4149 }
4150
4151 public String getPackageForIntentSender(IIntentSender pendingResult) {
4152 if (!(pendingResult instanceof PendingIntentRecord)) {
4153 return null;
4154 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004155 try {
4156 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4157 return res.key.packageName;
4158 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004159 }
4160 return null;
4161 }
4162
4163 public void setProcessLimit(int max) {
4164 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4165 "setProcessLimit()");
4166 mProcessLimit = max;
4167 }
4168
4169 public int getProcessLimit() {
4170 return mProcessLimit;
4171 }
4172
4173 void foregroundTokenDied(ForegroundToken token) {
4174 synchronized (ActivityManagerService.this) {
4175 synchronized (mPidsSelfLocked) {
4176 ForegroundToken cur
4177 = mForegroundProcesses.get(token.pid);
4178 if (cur != token) {
4179 return;
4180 }
4181 mForegroundProcesses.remove(token.pid);
4182 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4183 if (pr == null) {
4184 return;
4185 }
4186 pr.forcingToForeground = null;
4187 pr.foregroundServices = false;
4188 }
4189 updateOomAdjLocked();
4190 }
4191 }
4192
4193 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4194 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4195 "setProcessForeground()");
4196 synchronized(this) {
4197 boolean changed = false;
4198
4199 synchronized (mPidsSelfLocked) {
4200 ProcessRecord pr = mPidsSelfLocked.get(pid);
4201 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004202 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004203 return;
4204 }
4205 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4206 if (oldToken != null) {
4207 oldToken.token.unlinkToDeath(oldToken, 0);
4208 mForegroundProcesses.remove(pid);
4209 pr.forcingToForeground = null;
4210 changed = true;
4211 }
4212 if (isForeground && token != null) {
4213 ForegroundToken newToken = new ForegroundToken() {
4214 public void binderDied() {
4215 foregroundTokenDied(this);
4216 }
4217 };
4218 newToken.pid = pid;
4219 newToken.token = token;
4220 try {
4221 token.linkToDeath(newToken, 0);
4222 mForegroundProcesses.put(pid, newToken);
4223 pr.forcingToForeground = token;
4224 changed = true;
4225 } catch (RemoteException e) {
4226 // If the process died while doing this, we will later
4227 // do the cleanup with the process death link.
4228 }
4229 }
4230 }
4231
4232 if (changed) {
4233 updateOomAdjLocked();
4234 }
4235 }
4236 }
4237
4238 // =========================================================
4239 // PERMISSIONS
4240 // =========================================================
4241
4242 static class PermissionController extends IPermissionController.Stub {
4243 ActivityManagerService mActivityManagerService;
4244 PermissionController(ActivityManagerService activityManagerService) {
4245 mActivityManagerService = activityManagerService;
4246 }
4247
4248 public boolean checkPermission(String permission, int pid, int uid) {
4249 return mActivityManagerService.checkPermission(permission, pid,
4250 uid) == PackageManager.PERMISSION_GRANTED;
4251 }
4252 }
4253
4254 /**
4255 * This can be called with or without the global lock held.
4256 */
4257 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004258 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 // We might be performing an operation on behalf of an indirect binder
4260 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4261 // client identity accordingly before proceeding.
4262 Identity tlsIdentity = sCallerIdentity.get();
4263 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004264 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4266 uid = tlsIdentity.uid;
4267 pid = tlsIdentity.pid;
4268 }
4269
4270 // Root, system server and our own process get to do everything.
4271 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4272 !Process.supportsProcesses()) {
4273 return PackageManager.PERMISSION_GRANTED;
4274 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004275 // If there is a uid that owns whatever is being accessed, it has
4276 // blanket access to it regardless of the permissions it requires.
4277 if (owningUid >= 0 && uid == owningUid) {
4278 return PackageManager.PERMISSION_GRANTED;
4279 }
4280 // If the target is not exported, then nobody else can get to it.
4281 if (!exported) {
4282 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004283 return PackageManager.PERMISSION_DENIED;
4284 }
4285 if (permission == null) {
4286 return PackageManager.PERMISSION_GRANTED;
4287 }
4288 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004289 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 .checkUidPermission(permission, uid);
4291 } catch (RemoteException e) {
4292 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004293 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004294 }
4295 return PackageManager.PERMISSION_DENIED;
4296 }
4297
4298 /**
4299 * As the only public entry point for permissions checking, this method
4300 * can enforce the semantic that requesting a check on a null global
4301 * permission is automatically denied. (Internally a null permission
4302 * string is used when calling {@link #checkComponentPermission} in cases
4303 * when only uid-based security is needed.)
4304 *
4305 * This can be called with or without the global lock held.
4306 */
4307 public int checkPermission(String permission, int pid, int uid) {
4308 if (permission == null) {
4309 return PackageManager.PERMISSION_DENIED;
4310 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004311 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004312 }
4313
4314 /**
4315 * Binder IPC calls go through the public entry point.
4316 * This can be called with or without the global lock held.
4317 */
4318 int checkCallingPermission(String permission) {
4319 return checkPermission(permission,
4320 Binder.getCallingPid(),
4321 Binder.getCallingUid());
4322 }
4323
4324 /**
4325 * This can be called with or without the global lock held.
4326 */
4327 void enforceCallingPermission(String permission, String func) {
4328 if (checkCallingPermission(permission)
4329 == PackageManager.PERMISSION_GRANTED) {
4330 return;
4331 }
4332
4333 String msg = "Permission Denial: " + func + " from pid="
4334 + Binder.getCallingPid()
4335 + ", uid=" + Binder.getCallingUid()
4336 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004337 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338 throw new SecurityException(msg);
4339 }
4340
4341 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004342 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4343 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4344 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4345 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4346 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004348 // Is the component private from the target uid?
4349 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4350
4351 // Acceptable if the there is no read permission needed from the
4352 // target or the target is holding the read permission.
4353 if (!readPerm) {
4354 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004356 == PackageManager.PERMISSION_GRANTED)) {
4357 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358 }
4359 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004360
4361 // Acceptable if the there is no write permission needed from the
4362 // target or the target is holding the read permission.
4363 if (!writePerm) {
4364 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004365 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004366 == PackageManager.PERMISSION_GRANTED)) {
4367 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368 }
4369 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004370
4371 // Acceptable if there is a path permission matching the URI that
4372 // the target holds the permission on.
4373 PathPermission[] pps = pi.pathPermissions;
4374 if (pps != null && (!readPerm || !writePerm)) {
4375 final String path = uri.getPath();
4376 int i = pps.length;
4377 while (i > 0 && (!readPerm || !writePerm)) {
4378 i--;
4379 PathPermission pp = pps[i];
4380 if (!readPerm) {
4381 final String pprperm = pp.getReadPermission();
4382 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4383 + pprperm + " for " + pp.getPath()
4384 + ": match=" + pp.match(path)
4385 + " check=" + pm.checkUidPermission(pprperm, uid));
4386 if (pprperm != null && pp.match(path) &&
4387 (pm.checkUidPermission(pprperm, uid)
4388 == PackageManager.PERMISSION_GRANTED)) {
4389 readPerm = true;
4390 }
4391 }
4392 if (!writePerm) {
4393 final String ppwperm = pp.getWritePermission();
4394 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4395 + ppwperm + " for " + pp.getPath()
4396 + ": match=" + pp.match(path)
4397 + " check=" + pm.checkUidPermission(ppwperm, uid));
4398 if (ppwperm != null && pp.match(path) &&
4399 (pm.checkUidPermission(ppwperm, uid)
4400 == PackageManager.PERMISSION_GRANTED)) {
4401 writePerm = true;
4402 }
4403 }
4404 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 } catch (RemoteException e) {
4407 return false;
4408 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004409
4410 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004411 }
4412
4413 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4414 int modeFlags) {
4415 // Root gets to do everything.
4416 if (uid == 0 || !Process.supportsProcesses()) {
4417 return true;
4418 }
4419 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4420 if (perms == null) return false;
4421 UriPermission perm = perms.get(uri);
4422 if (perm == null) return false;
4423 return (modeFlags&perm.modeFlags) == modeFlags;
4424 }
4425
4426 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4427 // Another redirected-binder-call permissions check as in
4428 // {@link checkComponentPermission}.
4429 Identity tlsIdentity = sCallerIdentity.get();
4430 if (tlsIdentity != null) {
4431 uid = tlsIdentity.uid;
4432 pid = tlsIdentity.pid;
4433 }
4434
4435 // Our own process gets to do everything.
4436 if (pid == MY_PID) {
4437 return PackageManager.PERMISSION_GRANTED;
4438 }
4439 synchronized(this) {
4440 return checkUriPermissionLocked(uri, uid, modeFlags)
4441 ? PackageManager.PERMISSION_GRANTED
4442 : PackageManager.PERMISSION_DENIED;
4443 }
4444 }
4445
Dianne Hackborn39792d22010-08-19 18:01:52 -07004446 /**
4447 * Check if the targetPkg can be granted permission to access uri by
4448 * the callingUid using the given modeFlags. Throws a security exception
4449 * if callingUid is not allowed to do this. Returns the uid of the target
4450 * if the URI permission grant should be performed; returns -1 if it is not
4451 * needed (for example targetPkg already has permission to access the URI).
4452 */
4453 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4454 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4456 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4457 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004458 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004459 }
4460
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004461 if (targetPkg != null) {
4462 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4463 "Checking grant " + targetPkg + " permission to " + uri);
4464 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004465
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004466 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467
4468 // If this is not a content: uri, we can't do anything with it.
4469 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004470 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004471 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004472 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 }
4474
4475 String name = uri.getAuthority();
4476 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004477 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004478 if (cpr != null) {
4479 pi = cpr.info;
4480 } else {
4481 try {
4482 pi = pm.resolveContentProvider(name,
4483 PackageManager.GET_URI_PERMISSION_PATTERNS);
4484 } catch (RemoteException ex) {
4485 }
4486 }
4487 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004488 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004489 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 }
4491
4492 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004493 if (targetPkg != null) {
4494 try {
4495 targetUid = pm.getPackageUid(targetPkg);
4496 if (targetUid < 0) {
4497 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4498 "Can't grant URI permission no uid for: " + targetPkg);
4499 return -1;
4500 }
4501 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004502 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004504 } else {
4505 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 }
4507
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004508 if (targetUid >= 0) {
4509 // First... does the target actually need this permission?
4510 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4511 // No need to grant the target this permission.
4512 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4513 "Target " + targetPkg + " already has full permission to " + uri);
4514 return -1;
4515 }
4516 } else {
4517 // First... there is no target package, so can anyone access it?
4518 boolean allowed = pi.exported;
4519 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4520 if (pi.readPermission != null) {
4521 allowed = false;
4522 }
4523 }
4524 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4525 if (pi.writePermission != null) {
4526 allowed = false;
4527 }
4528 }
4529 if (allowed) {
4530 return -1;
4531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004532 }
4533
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004534 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004535 if (!pi.grantUriPermissions) {
4536 throw new SecurityException("Provider " + pi.packageName
4537 + "/" + pi.name
4538 + " does not allow granting of Uri permissions (uri "
4539 + uri + ")");
4540 }
4541 if (pi.uriPermissionPatterns != null) {
4542 final int N = pi.uriPermissionPatterns.length;
4543 boolean allowed = false;
4544 for (int i=0; i<N; i++) {
4545 if (pi.uriPermissionPatterns[i] != null
4546 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4547 allowed = true;
4548 break;
4549 }
4550 }
4551 if (!allowed) {
4552 throw new SecurityException("Provider " + pi.packageName
4553 + "/" + pi.name
4554 + " does not allow granting of permission to path of Uri "
4555 + uri);
4556 }
4557 }
4558
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004559 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004560 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004561 if (callingUid != Process.myUid()) {
4562 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4563 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4564 throw new SecurityException("Uid " + callingUid
4565 + " does not have permission to uri " + uri);
4566 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004567 }
4568 }
4569
Dianne Hackborn39792d22010-08-19 18:01:52 -07004570 return targetUid;
4571 }
4572
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004573 public int checkGrantUriPermission(int callingUid, String targetPkg,
4574 Uri uri, int modeFlags) {
4575 synchronized(this) {
4576 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4577 }
4578 }
4579
Dianne Hackborn39792d22010-08-19 18:01:52 -07004580 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4581 Uri uri, int modeFlags, UriPermissionOwner owner) {
4582 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4583 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4584 if (modeFlags == 0) {
4585 return;
4586 }
4587
4588 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004589 // to the uri, and the target doesn't. Let's now give this to
4590 // the target.
4591
Joe Onorato8a9b2202010-02-26 18:56:32 -08004592 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004593 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004595 HashMap<Uri, UriPermission> targetUris
4596 = mGrantedUriPermissions.get(targetUid);
4597 if (targetUris == null) {
4598 targetUris = new HashMap<Uri, UriPermission>();
4599 mGrantedUriPermissions.put(targetUid, targetUris);
4600 }
4601
4602 UriPermission perm = targetUris.get(uri);
4603 if (perm == null) {
4604 perm = new UriPermission(targetUid, uri);
4605 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004609 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004611 } else {
4612 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4613 perm.readOwners.add(owner);
4614 owner.addReadPermission(perm);
4615 }
4616 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4617 perm.writeOwners.add(owner);
4618 owner.addWritePermission(perm);
4619 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004620 }
4621 }
4622
Dianne Hackborn39792d22010-08-19 18:01:52 -07004623 void grantUriPermissionLocked(int callingUid,
4624 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004625 if (targetPkg == null) {
4626 throw new NullPointerException("targetPkg");
4627 }
4628
Dianne Hackborn39792d22010-08-19 18:01:52 -07004629 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4630 if (targetUid < 0) {
4631 return;
4632 }
4633
4634 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4635 }
4636
4637 /**
4638 * Like checkGrantUriPermissionLocked, but takes an Intent.
4639 */
4640 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4641 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004642 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004643 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004644 + " from " + intent + "; flags=0x"
4645 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4646
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004647 if (targetPkg == null) {
4648 throw new NullPointerException("targetPkg");
4649 }
4650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004651 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004652 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 }
4654 Uri data = intent.getData();
4655 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004656 return -1;
4657 }
4658 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4659 intent.getFlags());
4660 }
4661
4662 /**
4663 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4664 */
4665 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4666 String targetPkg, Intent intent, UriPermissionOwner owner) {
4667 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4668 intent.getFlags(), owner);
4669 }
4670
4671 void grantUriPermissionFromIntentLocked(int callingUid,
4672 String targetPkg, Intent intent, UriPermissionOwner owner) {
4673 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4674 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004675 return;
4676 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004677
4678 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 }
4680
4681 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4682 Uri uri, int modeFlags) {
4683 synchronized(this) {
4684 final ProcessRecord r = getRecordForAppLocked(caller);
4685 if (r == null) {
4686 throw new SecurityException("Unable to find app for caller "
4687 + caller
4688 + " when granting permission to uri " + uri);
4689 }
4690 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004691 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004692 }
4693 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004694 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 }
4696
4697 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4698 null);
4699 }
4700 }
4701
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004702 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004703 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4704 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4705 HashMap<Uri, UriPermission> perms
4706 = mGrantedUriPermissions.get(perm.uid);
4707 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004708 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004709 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004710 perms.remove(perm.uri);
4711 if (perms.size() == 0) {
4712 mGrantedUriPermissions.remove(perm.uid);
4713 }
4714 }
4715 }
4716 }
4717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004718 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4719 int modeFlags) {
4720 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4721 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4722 if (modeFlags == 0) {
4723 return;
4724 }
4725
Joe Onorato8a9b2202010-02-26 18:56:32 -08004726 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004727 "Revoking all granted permissions to " + uri);
4728
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004729 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730
4731 final String authority = uri.getAuthority();
4732 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004733 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 if (cpr != null) {
4735 pi = cpr.info;
4736 } else {
4737 try {
4738 pi = pm.resolveContentProvider(authority,
4739 PackageManager.GET_URI_PERMISSION_PATTERNS);
4740 } catch (RemoteException ex) {
4741 }
4742 }
4743 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004744 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004745 return;
4746 }
4747
4748 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004749 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750 // Right now, if you are not the original owner of the permission,
4751 // you are not allowed to revoke it.
4752 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4753 throw new SecurityException("Uid " + callingUid
4754 + " does not have permission to uri " + uri);
4755 //}
4756 }
4757
4758 // Go through all of the permissions and remove any that match.
4759 final List<String> SEGMENTS = uri.getPathSegments();
4760 if (SEGMENTS != null) {
4761 final int NS = SEGMENTS.size();
4762 int N = mGrantedUriPermissions.size();
4763 for (int i=0; i<N; i++) {
4764 HashMap<Uri, UriPermission> perms
4765 = mGrantedUriPermissions.valueAt(i);
4766 Iterator<UriPermission> it = perms.values().iterator();
4767 toploop:
4768 while (it.hasNext()) {
4769 UriPermission perm = it.next();
4770 Uri targetUri = perm.uri;
4771 if (!authority.equals(targetUri.getAuthority())) {
4772 continue;
4773 }
4774 List<String> targetSegments = targetUri.getPathSegments();
4775 if (targetSegments == null) {
4776 continue;
4777 }
4778 if (targetSegments.size() < NS) {
4779 continue;
4780 }
4781 for (int j=0; j<NS; j++) {
4782 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4783 continue toploop;
4784 }
4785 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004786 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004787 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 perm.clearModes(modeFlags);
4789 if (perm.modeFlags == 0) {
4790 it.remove();
4791 }
4792 }
4793 if (perms.size() == 0) {
4794 mGrantedUriPermissions.remove(
4795 mGrantedUriPermissions.keyAt(i));
4796 N--;
4797 i--;
4798 }
4799 }
4800 }
4801 }
4802
4803 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4804 int modeFlags) {
4805 synchronized(this) {
4806 final ProcessRecord r = getRecordForAppLocked(caller);
4807 if (r == null) {
4808 throw new SecurityException("Unable to find app for caller "
4809 + caller
4810 + " when revoking permission to uri " + uri);
4811 }
4812 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004813 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004814 return;
4815 }
4816
4817 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4818 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4819 if (modeFlags == 0) {
4820 return;
4821 }
4822
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004823 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004824
4825 final String authority = uri.getAuthority();
4826 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004827 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004828 if (cpr != null) {
4829 pi = cpr.info;
4830 } else {
4831 try {
4832 pi = pm.resolveContentProvider(authority,
4833 PackageManager.GET_URI_PERMISSION_PATTERNS);
4834 } catch (RemoteException ex) {
4835 }
4836 }
4837 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004838 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004839 return;
4840 }
4841
4842 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4843 }
4844 }
4845
Dianne Hackborn7e269642010-08-25 19:50:20 -07004846 @Override
4847 public IBinder newUriPermissionOwner(String name) {
4848 synchronized(this) {
4849 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4850 return owner.getExternalTokenLocked();
4851 }
4852 }
4853
4854 @Override
4855 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4856 Uri uri, int modeFlags) {
4857 synchronized(this) {
4858 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4859 if (owner == null) {
4860 throw new IllegalArgumentException("Unknown owner: " + token);
4861 }
4862 if (fromUid != Binder.getCallingUid()) {
4863 if (Binder.getCallingUid() != Process.myUid()) {
4864 // Only system code can grant URI permissions on behalf
4865 // of other users.
4866 throw new SecurityException("nice try");
4867 }
4868 }
4869 if (targetPkg == null) {
4870 throw new IllegalArgumentException("null target");
4871 }
4872 if (uri == null) {
4873 throw new IllegalArgumentException("null uri");
4874 }
4875
4876 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4877 }
4878 }
4879
4880 @Override
4881 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4882 synchronized(this) {
4883 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4884 if (owner == null) {
4885 throw new IllegalArgumentException("Unknown owner: " + token);
4886 }
4887
4888 if (uri == null) {
4889 owner.removeUriPermissionsLocked(mode);
4890 } else {
4891 owner.removeUriPermissionLocked(uri, mode);
4892 }
4893 }
4894 }
4895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4897 synchronized (this) {
4898 ProcessRecord app =
4899 who != null ? getRecordForAppLocked(who) : null;
4900 if (app == null) return;
4901
4902 Message msg = Message.obtain();
4903 msg.what = WAIT_FOR_DEBUGGER_MSG;
4904 msg.obj = app;
4905 msg.arg1 = waiting ? 1 : 0;
4906 mHandler.sendMessage(msg);
4907 }
4908 }
4909
4910 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4911 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004912 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004913 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004914 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 }
4916
4917 // =========================================================
4918 // TASK MANAGEMENT
4919 // =========================================================
4920
4921 public List getTasks(int maxNum, int flags,
4922 IThumbnailReceiver receiver) {
4923 ArrayList list = new ArrayList();
4924
4925 PendingThumbnailsRecord pending = null;
4926 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004927 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928
4929 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004930 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004931 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4932 + ", receiver=" + receiver);
4933
4934 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4935 != PackageManager.PERMISSION_GRANTED) {
4936 if (receiver != null) {
4937 // If the caller wants to wait for pending thumbnails,
4938 // it ain't gonna get them.
4939 try {
4940 receiver.finished();
4941 } catch (RemoteException ex) {
4942 }
4943 }
4944 String msg = "Permission Denial: getTasks() from pid="
4945 + Binder.getCallingPid()
4946 + ", uid=" + Binder.getCallingUid()
4947 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004948 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949 throw new SecurityException(msg);
4950 }
4951
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004952 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004953 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004954 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004955 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004956 TaskRecord curTask = null;
4957 int numActivities = 0;
4958 int numRunning = 0;
4959 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004960 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004962 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963
4964 // Initialize state for next task if needed.
4965 if (top == null ||
4966 (top.state == ActivityState.INITIALIZING
4967 && top.task == r.task)) {
4968 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004969 curTask = r.task;
4970 numActivities = numRunning = 0;
4971 }
4972
4973 // Add 'r' into the current task.
4974 numActivities++;
4975 if (r.app != null && r.app.thread != null) {
4976 numRunning++;
4977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004978
Joe Onorato8a9b2202010-02-26 18:56:32 -08004979 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980 TAG, r.intent.getComponent().flattenToShortString()
4981 + ": task=" + r.task);
4982
4983 // If the next one is a different task, generate a new
4984 // TaskInfo entry for what we have.
4985 if (next == null || next.task != curTask) {
4986 ActivityManager.RunningTaskInfo ci
4987 = new ActivityManager.RunningTaskInfo();
4988 ci.id = curTask.taskId;
4989 ci.baseActivity = r.intent.getComponent();
4990 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07004991 if (top.thumbHolder != null) {
4992 ci.description = top.thumbHolder.lastDescription;
4993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004994 ci.numActivities = numActivities;
4995 ci.numRunning = numRunning;
4996 //System.out.println(
4997 // "#" + maxNum + ": " + " descr=" + ci.description);
4998 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004999 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 TAG, "State=" + top.state + "Idle=" + top.idle
5001 + " app=" + top.app
5002 + " thr=" + (top.app != null ? top.app.thread : null));
5003 if (top.state == ActivityState.RESUMED
5004 || top.state == ActivityState.PAUSING) {
5005 if (top.idle && top.app != null
5006 && top.app.thread != null) {
5007 topRecord = top;
5008 topThumbnail = top.app.thread;
5009 } else {
5010 top.thumbnailNeeded = true;
5011 }
5012 }
5013 if (pending == null) {
5014 pending = new PendingThumbnailsRecord(receiver);
5015 }
5016 pending.pendingRecords.add(top);
5017 }
5018 list.add(ci);
5019 maxNum--;
5020 top = null;
5021 }
5022 }
5023
5024 if (pending != null) {
5025 mPendingThumbnails.add(pending);
5026 }
5027 }
5028
Joe Onorato8a9b2202010-02-26 18:56:32 -08005029 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030
5031 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005032 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005033 try {
5034 topThumbnail.requestThumbnail(topRecord);
5035 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005036 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 sendPendingThumbnail(null, topRecord, null, null, true);
5038 }
5039 }
5040
5041 if (pending == null && receiver != null) {
5042 // In this case all thumbnails were available and the client
5043 // is being asked to be told when the remaining ones come in...
5044 // which is unusually, since the top-most currently running
5045 // activity should never have a canned thumbnail! Oh well.
5046 try {
5047 receiver.finished();
5048 } catch (RemoteException ex) {
5049 }
5050 }
5051
5052 return list;
5053 }
5054
5055 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5056 int flags) {
5057 synchronized (this) {
5058 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5059 "getRecentTasks()");
5060
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005061 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 final int N = mRecentTasks.size();
5064 ArrayList<ActivityManager.RecentTaskInfo> res
5065 = new ArrayList<ActivityManager.RecentTaskInfo>(
5066 maxNum < N ? maxNum : N);
5067 for (int i=0; i<N && maxNum > 0; i++) {
5068 TaskRecord tr = mRecentTasks.get(i);
5069 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
5070 || (tr.intent == null)
5071 || ((tr.intent.getFlags()
5072 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5073 ActivityManager.RecentTaskInfo rti
5074 = new ActivityManager.RecentTaskInfo();
5075 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005076 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 rti.baseIntent = new Intent(
5078 tr.intent != null ? tr.intent : tr.affinityIntent);
5079 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005080 rti.description = tr.lastDescription;
5081
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005082 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5083 // Check whether this activity is currently available.
5084 try {
5085 if (rti.origActivity != null) {
5086 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5087 continue;
5088 }
5089 } else if (rti.baseIntent != null) {
5090 if (pm.queryIntentActivities(rti.baseIntent,
5091 null, 0) == null) {
5092 continue;
5093 }
5094 }
5095 } catch (RemoteException e) {
5096 // Will never happen.
5097 }
5098 }
5099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 res.add(rti);
5101 maxNum--;
5102 }
5103 }
5104 return res;
5105 }
5106 }
5107
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005108 private TaskRecord taskForIdLocked(int id) {
5109 final int N = mRecentTasks.size();
5110 for (int i=0; i<N; i++) {
5111 TaskRecord tr = mRecentTasks.get(i);
5112 if (tr.taskId == id) {
5113 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005114 }
5115 }
5116 return null;
5117 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005118
5119 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5120 synchronized (this) {
5121 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5122 "getTaskThumbnails()");
5123 TaskRecord tr = taskForIdLocked(id);
5124 if (tr != null) {
5125 return mMainStack.getTaskThumbnailsLocked(tr);
5126 }
5127 }
5128 return null;
5129 }
5130
5131 public boolean removeSubTask(int taskId, int subTaskIndex) {
5132 synchronized (this) {
5133 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5134 "removeSubTask()");
5135 long ident = Binder.clearCallingIdentity();
5136 try {
5137 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5138 } finally {
5139 Binder.restoreCallingIdentity(ident);
5140 }
5141 }
5142 }
5143
5144 private void removeTaskProcessesLocked(ActivityRecord root) {
5145 TaskRecord tr = root.task;
5146 Intent baseIntent = new Intent(
5147 tr.intent != null ? tr.intent : tr.affinityIntent);
5148 ComponentName component = baseIntent.getComponent();
5149 if (component == null) {
5150 Slog.w(TAG, "Now component for base intent of task: " + tr);
5151 return;
5152 }
5153
5154 // Find any running services associated with this app.
5155 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5156 for (ServiceRecord sr : mServices.values()) {
5157 if (sr.packageName.equals(component.getPackageName())) {
5158 services.add(sr);
5159 }
5160 }
5161
5162 // Take care of any running services associated with the app.
5163 for (int i=0; i<services.size(); i++) {
5164 ServiceRecord sr = services.get(i);
5165 if (sr.startRequested) {
5166 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
5167 stopServiceLocked(sr);
5168 } else {
5169 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5170 sr.makeNextStartId(), baseIntent, -1));
5171 if (sr.app != null && sr.app.thread != null) {
5172 sendServiceArgsLocked(sr, false);
5173 }
5174 }
5175 }
5176 }
5177
5178 // Find any running processes associated with this app.
5179 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5180 SparseArray<ProcessRecord> appProcs
5181 = mProcessNames.getMap().get(component.getPackageName());
5182 if (appProcs != null) {
5183 for (int i=0; i<appProcs.size(); i++) {
5184 procs.add(appProcs.valueAt(i));
5185 }
5186 }
5187
5188 // Kill the running processes.
5189 for (int i=0; i<procs.size(); i++) {
5190 ProcessRecord pr = procs.get(i);
5191 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5192 Slog.i(TAG, "Killing " + pr + ": remove task");
5193 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5194 pr.processName, pr.setAdj, "remove task");
5195 Process.killProcessQuiet(pr.pid);
5196 } else {
5197 pr.waitingToKill = "remove task";
5198 }
5199 }
5200 }
5201
5202 public boolean removeTask(int taskId, int flags) {
5203 synchronized (this) {
5204 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5205 "removeTask()");
5206 long ident = Binder.clearCallingIdentity();
5207 try {
5208 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5209 if (r != null) {
5210 mRecentTasks.remove(r.task);
5211
5212 if ((flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0) {
5213 removeTaskProcessesLocked(r);
5214 }
5215
5216 return true;
5217 }
5218 } finally {
5219 Binder.restoreCallingIdentity(ident);
5220 }
5221 }
5222 return false;
5223 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5226 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005227 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 TaskRecord jt = startTask;
5229
5230 // First look backwards
5231 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005232 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 if (r.task != jt) {
5234 jt = r.task;
5235 if (affinity.equals(jt.affinity)) {
5236 return j;
5237 }
5238 }
5239 }
5240
5241 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005242 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 jt = startTask;
5244 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005245 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005246 if (r.task != jt) {
5247 if (affinity.equals(jt.affinity)) {
5248 return j;
5249 }
5250 jt = r.task;
5251 }
5252 }
5253
5254 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005255 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 return N-1;
5257 }
5258
5259 return -1;
5260 }
5261
5262 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005263 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005264 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005265 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5267 "moveTaskToFront()");
5268
5269 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005270 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5271 Binder.getCallingUid(), "Task to front")) {
5272 return;
5273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 final long origId = Binder.clearCallingIdentity();
5275 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005276 TaskRecord tr = taskForIdLocked(task);
5277 if (tr != null) {
5278 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5279 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005281 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5282 // Caller wants the home activity moved with it. To accomplish this,
5283 // we'll just move the home task to the top first.
5284 mMainStack.moveHomeToFrontLocked();
5285 }
5286 mMainStack.moveTaskToFrontLocked(tr, null);
5287 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005288 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005289 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5290 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005291 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005292 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5293 mMainStack.mUserLeaving = true;
5294 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005295 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5296 // Caller wants the home activity moved with it. To accomplish this,
5297 // we'll just move the home task to the top first.
5298 mMainStack.moveHomeToFrontLocked();
5299 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005300 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 return;
5302 }
5303 }
5304 } finally {
5305 Binder.restoreCallingIdentity(origId);
5306 }
5307 }
5308 }
5309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 public void moveTaskToBack(int task) {
5311 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5312 "moveTaskToBack()");
5313
5314 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005315 if (mMainStack.mResumedActivity != null
5316 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005317 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5318 Binder.getCallingUid(), "Task to back")) {
5319 return;
5320 }
5321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005323 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 Binder.restoreCallingIdentity(origId);
5325 }
5326 }
5327
5328 /**
5329 * Moves an activity, and all of the other activities within the same task, to the bottom
5330 * of the history stack. The activity's order within the task is unchanged.
5331 *
5332 * @param token A reference to the activity we wish to move
5333 * @param nonRoot If false then this only works if the activity is the root
5334 * of a task; if true it will work for any activity in a task.
5335 * @return Returns true if the move completed, false if not.
5336 */
5337 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5338 synchronized(this) {
5339 final long origId = Binder.clearCallingIdentity();
5340 int taskId = getTaskForActivityLocked(token, !nonRoot);
5341 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005342 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 }
5344 Binder.restoreCallingIdentity(origId);
5345 }
5346 return false;
5347 }
5348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 public void moveTaskBackwards(int task) {
5350 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5351 "moveTaskBackwards()");
5352
5353 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005354 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5355 Binder.getCallingUid(), "Task backwards")) {
5356 return;
5357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 final long origId = Binder.clearCallingIdentity();
5359 moveTaskBackwardsLocked(task);
5360 Binder.restoreCallingIdentity(origId);
5361 }
5362 }
5363
5364 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005365 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005366 }
5367
5368 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5369 synchronized(this) {
5370 return getTaskForActivityLocked(token, onlyRoot);
5371 }
5372 }
5373
5374 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005375 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005376 TaskRecord lastTask = null;
5377 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005378 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 if (r == token) {
5380 if (!onlyRoot || lastTask != r.task) {
5381 return r.task.taskId;
5382 }
5383 return -1;
5384 }
5385 lastTask = r.task;
5386 }
5387
5388 return -1;
5389 }
5390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005391 public void finishOtherInstances(IBinder token, ComponentName className) {
5392 synchronized(this) {
5393 final long origId = Binder.clearCallingIdentity();
5394
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005395 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 TaskRecord lastTask = null;
5397 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005398 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005399 if (r.realActivity.equals(className)
5400 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005401 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005402 null, "others")) {
5403 i--;
5404 N--;
5405 }
5406 }
5407 lastTask = r.task;
5408 }
5409
5410 Binder.restoreCallingIdentity(origId);
5411 }
5412 }
5413
5414 // =========================================================
5415 // THUMBNAILS
5416 // =========================================================
5417
5418 public void reportThumbnail(IBinder token,
5419 Bitmap thumbnail, CharSequence description) {
5420 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5421 final long origId = Binder.clearCallingIdentity();
5422 sendPendingThumbnail(null, token, thumbnail, description, true);
5423 Binder.restoreCallingIdentity(origId);
5424 }
5425
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005426 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 Bitmap thumbnail, CharSequence description, boolean always) {
5428 TaskRecord task = null;
5429 ArrayList receivers = null;
5430
5431 //System.out.println("Send pending thumbnail: " + r);
5432
5433 synchronized(this) {
5434 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005435 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005436 if (index < 0) {
5437 return;
5438 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005439 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005440 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005441 if (thumbnail == null && r.thumbHolder != null) {
5442 thumbnail = r.thumbHolder.lastThumbnail;
5443 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005444 }
5445 if (thumbnail == null && !always) {
5446 // If there is no thumbnail, and this entry is not actually
5447 // going away, then abort for now and pick up the next
5448 // thumbnail we get.
5449 return;
5450 }
5451 task = r.task;
5452
5453 int N = mPendingThumbnails.size();
5454 int i=0;
5455 while (i<N) {
5456 PendingThumbnailsRecord pr =
5457 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5458 //System.out.println("Looking in " + pr.pendingRecords);
5459 if (pr.pendingRecords.remove(r)) {
5460 if (receivers == null) {
5461 receivers = new ArrayList();
5462 }
5463 receivers.add(pr);
5464 if (pr.pendingRecords.size() == 0) {
5465 pr.finished = true;
5466 mPendingThumbnails.remove(i);
5467 N--;
5468 continue;
5469 }
5470 }
5471 i++;
5472 }
5473 }
5474
5475 if (receivers != null) {
5476 final int N = receivers.size();
5477 for (int i=0; i<N; i++) {
5478 try {
5479 PendingThumbnailsRecord pr =
5480 (PendingThumbnailsRecord)receivers.get(i);
5481 pr.receiver.newThumbnail(
5482 task != null ? task.taskId : -1, thumbnail, description);
5483 if (pr.finished) {
5484 pr.receiver.finished();
5485 }
5486 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005487 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 }
5489 }
5490 }
5491 }
5492
5493 // =========================================================
5494 // CONTENT PROVIDERS
5495 // =========================================================
5496
5497 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5498 List providers = null;
5499 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005500 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005502 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005503 } catch (RemoteException ex) {
5504 }
5505 if (providers != null) {
5506 final int N = providers.size();
5507 for (int i=0; i<N; i++) {
5508 ProviderInfo cpi =
5509 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005510 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 if (cpr == null) {
5512 cpr = new ContentProviderRecord(cpi, app.info);
5513 mProvidersByClass.put(cpi.name, cpr);
5514 }
5515 app.pubProviders.put(cpi.name, cpr);
5516 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005517 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005518 }
5519 }
5520 return providers;
5521 }
5522
5523 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005524 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005525 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5526 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5527 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005528 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005529 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 return null;
5531 }
5532 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005533 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 == PackageManager.PERMISSION_GRANTED) {
5535 return null;
5536 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005537
5538 PathPermission[] pps = cpi.pathPermissions;
5539 if (pps != null) {
5540 int i = pps.length;
5541 while (i > 0) {
5542 i--;
5543 PathPermission pp = pps[i];
5544 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005545 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005546 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005547 return null;
5548 }
5549 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005550 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005551 == PackageManager.PERMISSION_GRANTED) {
5552 return null;
5553 }
5554 }
5555 }
5556
Dianne Hackbornb424b632010-08-18 15:59:05 -07005557 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5558 if (perms != null) {
5559 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5560 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5561 return null;
5562 }
5563 }
5564 }
5565
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005566 String msg;
5567 if (!cpi.exported) {
5568 msg = "Permission Denial: opening provider " + cpi.name
5569 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5570 + ", uid=" + callingUid + ") that is not exported from uid "
5571 + cpi.applicationInfo.uid;
5572 } else {
5573 msg = "Permission Denial: opening provider " + cpi.name
5574 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5575 + ", uid=" + callingUid + ") requires "
5576 + cpi.readPermission + " or " + cpi.writePermission;
5577 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005578 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005579 return msg;
5580 }
5581
5582 private final ContentProviderHolder getContentProviderImpl(
5583 IApplicationThread caller, String name) {
5584 ContentProviderRecord cpr;
5585 ProviderInfo cpi = null;
5586
5587 synchronized(this) {
5588 ProcessRecord r = null;
5589 if (caller != null) {
5590 r = getRecordForAppLocked(caller);
5591 if (r == null) {
5592 throw new SecurityException(
5593 "Unable to find app for caller " + caller
5594 + " (pid=" + Binder.getCallingPid()
5595 + ") when getting content provider " + name);
5596 }
5597 }
5598
5599 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005600 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005601 if (cpr != null) {
5602 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005603 String msg;
5604 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5605 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005606 }
5607
5608 if (r != null && cpr.canRunHere(r)) {
5609 // This provider has been published or is in the process
5610 // of being published... but it is also allowed to run
5611 // in the caller's process, so don't make a connection
5612 // and just let the caller instantiate its own instance.
5613 if (cpr.provider != null) {
5614 // don't give caller the provider object, it needs
5615 // to make its own.
5616 cpr = new ContentProviderRecord(cpr);
5617 }
5618 return cpr;
5619 }
5620
5621 final long origId = Binder.clearCallingIdentity();
5622
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005623 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005624 // return it right away.
5625 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005626 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005627 "Adding provider requested by "
5628 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005629 + cpr.info.processName);
5630 Integer cnt = r.conProviders.get(cpr);
5631 if (cnt == null) {
5632 r.conProviders.put(cpr, new Integer(1));
5633 } else {
5634 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005637 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5638 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005639 // make sure to count it as being accessed and thus
5640 // back up on the LRU list. This is good because
5641 // content providers are often expensive to start.
5642 updateLruProcessLocked(cpr.app, false, true);
5643 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005644 } else {
5645 cpr.externals++;
5646 }
5647
5648 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 updateOomAdjLocked(cpr.app);
5650 }
5651
5652 Binder.restoreCallingIdentity(origId);
5653
5654 } else {
5655 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005656 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005657 resolveContentProvider(name,
5658 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005659 } catch (RemoteException ex) {
5660 }
5661 if (cpi == null) {
5662 return null;
5663 }
5664
Dianne Hackbornb424b632010-08-18 15:59:05 -07005665 String msg;
5666 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5667 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005668 }
5669
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005670 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005671 && !cpi.processName.equals("system")) {
5672 // If this content provider does not run in the system
5673 // process, and the system is not yet ready to run other
5674 // processes, then fail fast instead of hanging.
5675 throw new IllegalArgumentException(
5676 "Attempt to launch content provider before system ready");
5677 }
5678
Dianne Hackborn860755f2010-06-03 18:47:52 -07005679 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005680 final boolean firstClass = cpr == null;
5681 if (firstClass) {
5682 try {
5683 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005684 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005685 getApplicationInfo(
5686 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005687 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005688 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005689 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005690 + cpi.name);
5691 return null;
5692 }
5693 cpr = new ContentProviderRecord(cpi, ai);
5694 } catch (RemoteException ex) {
5695 // pm is in same process, this will never happen.
5696 }
5697 }
5698
5699 if (r != null && cpr.canRunHere(r)) {
5700 // If this is a multiprocess provider, then just return its
5701 // info and allow the caller to instantiate it. Only do
5702 // this if the provider is the same user as the caller's
5703 // process, or can run as root (so can be in any process).
5704 return cpr;
5705 }
5706
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005707 if (DEBUG_PROVIDER) {
5708 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005709 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005710 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005711 }
5712
5713 // This is single process, and our app is now connecting to it.
5714 // See if we are already in the process of launching this
5715 // provider.
5716 final int N = mLaunchingProviders.size();
5717 int i;
5718 for (i=0; i<N; i++) {
5719 if (mLaunchingProviders.get(i) == cpr) {
5720 break;
5721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005722 }
5723
5724 // If the provider is not already being launched, then get it
5725 // started.
5726 if (i >= N) {
5727 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005728
5729 try {
5730 // Content provider is now in use, its package can't be stopped.
5731 try {
5732 AppGlobals.getPackageManager().setPackageStoppedState(
5733 cpr.appInfo.packageName, false);
5734 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005735 } catch (IllegalArgumentException e) {
5736 Slog.w(TAG, "Failed trying to unstop package "
5737 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005738 }
5739
5740 ProcessRecord proc = startProcessLocked(cpi.processName,
5741 cpr.appInfo, false, 0, "content provider",
5742 new ComponentName(cpi.applicationInfo.packageName,
5743 cpi.name), false);
5744 if (proc == null) {
5745 Slog.w(TAG, "Unable to launch app "
5746 + cpi.applicationInfo.packageName + "/"
5747 + cpi.applicationInfo.uid + " for provider "
5748 + name + ": process is bad");
5749 return null;
5750 }
5751 cpr.launchingApp = proc;
5752 mLaunchingProviders.add(cpr);
5753 } finally {
5754 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005755 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005756 }
5757
5758 // Make sure the provider is published (the same provider class
5759 // may be published under multiple names).
5760 if (firstClass) {
5761 mProvidersByClass.put(cpi.name, cpr);
5762 }
5763 mProvidersByName.put(name, cpr);
5764
5765 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005766 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005767 "Adding provider requested by "
5768 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005769 + cpr.info.processName);
5770 Integer cnt = r.conProviders.get(cpr);
5771 if (cnt == null) {
5772 r.conProviders.put(cpr, new Integer(1));
5773 } else {
5774 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005776 cpr.clients.add(r);
5777 } else {
5778 cpr.externals++;
5779 }
5780 }
5781 }
5782
5783 // Wait for the provider to be published...
5784 synchronized (cpr) {
5785 while (cpr.provider == null) {
5786 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005787 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005788 + cpi.applicationInfo.packageName + "/"
5789 + cpi.applicationInfo.uid + " for provider "
5790 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005791 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005792 cpi.applicationInfo.packageName,
5793 cpi.applicationInfo.uid, name);
5794 return null;
5795 }
5796 try {
5797 cpr.wait();
5798 } catch (InterruptedException ex) {
5799 }
5800 }
5801 }
5802 return cpr;
5803 }
5804
5805 public final ContentProviderHolder getContentProvider(
5806 IApplicationThread caller, String name) {
5807 if (caller == null) {
5808 String msg = "null IApplicationThread when getting content provider "
5809 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005810 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005811 throw new SecurityException(msg);
5812 }
5813
5814 return getContentProviderImpl(caller, name);
5815 }
5816
5817 private ContentProviderHolder getContentProviderExternal(String name) {
5818 return getContentProviderImpl(null, name);
5819 }
5820
5821 /**
5822 * Drop a content provider from a ProcessRecord's bookkeeping
5823 * @param cpr
5824 */
5825 public void removeContentProvider(IApplicationThread caller, String name) {
5826 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005827 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005829 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005830 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005831 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005832 return;
5833 }
5834 final ProcessRecord r = getRecordForAppLocked(caller);
5835 if (r == null) {
5836 throw new SecurityException(
5837 "Unable to find app for caller " + caller +
5838 " when removing content provider " + name);
5839 }
5840 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005841 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005842 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005843 + r.info.processName + " from process "
5844 + localCpr.appInfo.processName);
5845 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005846 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005847 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005848 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005849 return;
5850 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005851 Integer cnt = r.conProviders.get(localCpr);
5852 if (cnt == null || cnt.intValue() <= 1) {
5853 localCpr.clients.remove(r);
5854 r.conProviders.remove(localCpr);
5855 } else {
5856 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005858 }
5859 updateOomAdjLocked();
5860 }
5861 }
5862
5863 private void removeContentProviderExternal(String name) {
5864 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005865 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005866 if(cpr == null) {
5867 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005868 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005869 return;
5870 }
5871
5872 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005873 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005874 localCpr.externals--;
5875 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005876 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005877 }
5878 updateOomAdjLocked();
5879 }
5880 }
5881
5882 public final void publishContentProviders(IApplicationThread caller,
5883 List<ContentProviderHolder> providers) {
5884 if (providers == null) {
5885 return;
5886 }
5887
5888 synchronized(this) {
5889 final ProcessRecord r = getRecordForAppLocked(caller);
5890 if (r == null) {
5891 throw new SecurityException(
5892 "Unable to find app for caller " + caller
5893 + " (pid=" + Binder.getCallingPid()
5894 + ") when publishing content providers");
5895 }
5896
5897 final long origId = Binder.clearCallingIdentity();
5898
5899 final int N = providers.size();
5900 for (int i=0; i<N; i++) {
5901 ContentProviderHolder src = providers.get(i);
5902 if (src == null || src.info == null || src.provider == null) {
5903 continue;
5904 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005905 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005906 if (dst != null) {
5907 mProvidersByClass.put(dst.info.name, dst);
5908 String names[] = dst.info.authority.split(";");
5909 for (int j = 0; j < names.length; j++) {
5910 mProvidersByName.put(names[j], dst);
5911 }
5912
5913 int NL = mLaunchingProviders.size();
5914 int j;
5915 for (j=0; j<NL; j++) {
5916 if (mLaunchingProviders.get(j) == dst) {
5917 mLaunchingProviders.remove(j);
5918 j--;
5919 NL--;
5920 }
5921 }
5922 synchronized (dst) {
5923 dst.provider = src.provider;
5924 dst.app = r;
5925 dst.notifyAll();
5926 }
5927 updateOomAdjLocked(r);
5928 }
5929 }
5930
5931 Binder.restoreCallingIdentity(origId);
5932 }
5933 }
5934
5935 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005936 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005937 synchronized (mSelf) {
5938 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5939 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005940 if (providers != null) {
5941 for (int i=providers.size()-1; i>=0; i--) {
5942 ProviderInfo pi = (ProviderInfo)providers.get(i);
5943 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5944 Slog.w(TAG, "Not installing system proc provider " + pi.name
5945 + ": not system .apk");
5946 providers.remove(i);
5947 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005948 }
5949 }
5950 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005951 if (providers != null) {
5952 mSystemThread.installSystemProviders(providers);
5953 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005954
5955 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005956 }
5957
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005958 /**
5959 * Allows app to retrieve the MIME type of a URI without having permission
5960 * to access its content provider.
5961 *
5962 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5963 *
5964 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5965 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5966 */
5967 public String getProviderMimeType(Uri uri) {
5968 final String name = uri.getAuthority();
5969 final long ident = Binder.clearCallingIdentity();
5970 ContentProviderHolder holder = null;
5971
5972 try {
5973 holder = getContentProviderExternal(name);
5974 if (holder != null) {
5975 return holder.provider.getType(uri);
5976 }
5977 } catch (RemoteException e) {
5978 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5979 return null;
5980 } finally {
5981 if (holder != null) {
5982 removeContentProviderExternal(name);
5983 }
5984 Binder.restoreCallingIdentity(ident);
5985 }
5986
5987 return null;
5988 }
5989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005990 // =========================================================
5991 // GLOBAL MANAGEMENT
5992 // =========================================================
5993
5994 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5995 ApplicationInfo info, String customProcess) {
5996 String proc = customProcess != null ? customProcess : info.processName;
5997 BatteryStatsImpl.Uid.Proc ps = null;
5998 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5999 synchronized (stats) {
6000 ps = stats.getProcessStatsLocked(info.uid, proc);
6001 }
6002 return new ProcessRecord(ps, thread, info, proc);
6003 }
6004
6005 final ProcessRecord addAppLocked(ApplicationInfo info) {
6006 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
6007
6008 if (app == null) {
6009 app = newProcessRecordLocked(null, info, null);
6010 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006011 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006012 }
6013
Dianne Hackborne7f97212011-02-24 14:40:20 -08006014 // This package really, really can not be stopped.
6015 try {
6016 AppGlobals.getPackageManager().setPackageStoppedState(
6017 info.packageName, false);
6018 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006019 } catch (IllegalArgumentException e) {
6020 Slog.w(TAG, "Failed trying to unstop package "
6021 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006022 }
6023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006024 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6025 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6026 app.persistent = true;
6027 app.maxAdj = CORE_SERVER_ADJ;
6028 }
6029 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6030 mPersistentStartingProcesses.add(app);
6031 startProcessLocked(app, "added application", app.processName);
6032 }
6033
6034 return app;
6035 }
6036
6037 public void unhandledBack() {
6038 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6039 "unhandledBack()");
6040
6041 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006042 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006043 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006044 TAG, "Performing unhandledBack(): stack size = " + count);
6045 if (count > 1) {
6046 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006047 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6049 Binder.restoreCallingIdentity(origId);
6050 }
6051 }
6052 }
6053
6054 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6055 String name = uri.getAuthority();
6056 ContentProviderHolder cph = getContentProviderExternal(name);
6057 ParcelFileDescriptor pfd = null;
6058 if (cph != null) {
6059 // We record the binder invoker's uid in thread-local storage before
6060 // going to the content provider to open the file. Later, in the code
6061 // that handles all permissions checks, we look for this uid and use
6062 // that rather than the Activity Manager's own uid. The effect is that
6063 // we do the check against the caller's permissions even though it looks
6064 // to the content provider like the Activity Manager itself is making
6065 // the request.
6066 sCallerIdentity.set(new Identity(
6067 Binder.getCallingPid(), Binder.getCallingUid()));
6068 try {
6069 pfd = cph.provider.openFile(uri, "r");
6070 } catch (FileNotFoundException e) {
6071 // do nothing; pfd will be returned null
6072 } finally {
6073 // Ensure that whatever happens, we clean up the identity state
6074 sCallerIdentity.remove();
6075 }
6076
6077 // We've got the fd now, so we're done with the provider.
6078 removeContentProviderExternal(name);
6079 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006080 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006081 }
6082 return pfd;
6083 }
6084
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006085 // Actually is sleeping or shutting down or whatever else in the future
6086 // is an inactive state.
6087 public boolean isSleeping() {
6088 return mSleeping || mShuttingDown;
6089 }
6090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006091 public void goingToSleep() {
6092 synchronized(this) {
6093 mSleeping = true;
6094 mWindowManager.setEventDispatching(false);
6095
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006096 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006097
6098 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006099 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006100 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6101 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006102 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006103 }
6104 }
6105
Dianne Hackborn55280a92009-05-07 15:53:46 -07006106 public boolean shutdown(int timeout) {
6107 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6108 != PackageManager.PERMISSION_GRANTED) {
6109 throw new SecurityException("Requires permission "
6110 + android.Manifest.permission.SHUTDOWN);
6111 }
6112
6113 boolean timedout = false;
6114
6115 synchronized(this) {
6116 mShuttingDown = true;
6117 mWindowManager.setEventDispatching(false);
6118
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006119 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006120 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006121 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006122 while (mMainStack.mResumedActivity != null
6123 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006124 long delay = endTime - System.currentTimeMillis();
6125 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006126 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006127 timedout = true;
6128 break;
6129 }
6130 try {
6131 this.wait();
6132 } catch (InterruptedException e) {
6133 }
6134 }
6135 }
6136 }
6137
6138 mUsageStatsService.shutdown();
6139 mBatteryStatsService.shutdown();
6140
6141 return timedout;
6142 }
6143
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006144 public final void activitySlept(IBinder token) {
6145 if (localLOGV) Slog.v(
6146 TAG, "Activity slept: token=" + token);
6147
6148 ActivityRecord r = null;
6149
6150 final long origId = Binder.clearCallingIdentity();
6151
6152 synchronized (this) {
6153 int index = mMainStack.indexOfTokenLocked(token);
6154 if (index >= 0) {
6155 r = (ActivityRecord)mMainStack.mHistory.get(index);
6156 mMainStack.activitySleptLocked(r);
6157 }
6158 }
6159
6160 Binder.restoreCallingIdentity(origId);
6161 }
6162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006163 public void wakingUp() {
6164 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006165 mWindowManager.setEventDispatching(true);
6166 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006167 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006168 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006169 }
6170 }
6171
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006172 public void stopAppSwitches() {
6173 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6174 != PackageManager.PERMISSION_GRANTED) {
6175 throw new SecurityException("Requires permission "
6176 + android.Manifest.permission.STOP_APP_SWITCHES);
6177 }
6178
6179 synchronized(this) {
6180 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6181 + APP_SWITCH_DELAY_TIME;
6182 mDidAppSwitch = false;
6183 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6184 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6185 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6186 }
6187 }
6188
6189 public void resumeAppSwitches() {
6190 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6191 != PackageManager.PERMISSION_GRANTED) {
6192 throw new SecurityException("Requires permission "
6193 + android.Manifest.permission.STOP_APP_SWITCHES);
6194 }
6195
6196 synchronized(this) {
6197 // Note that we don't execute any pending app switches... we will
6198 // let those wait until either the timeout, or the next start
6199 // activity request.
6200 mAppSwitchesAllowedTime = 0;
6201 }
6202 }
6203
6204 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6205 String name) {
6206 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6207 return true;
6208 }
6209
6210 final int perm = checkComponentPermission(
6211 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006212 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006213 if (perm == PackageManager.PERMISSION_GRANTED) {
6214 return true;
6215 }
6216
Joe Onorato8a9b2202010-02-26 18:56:32 -08006217 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006218 return false;
6219 }
6220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006221 public void setDebugApp(String packageName, boolean waitForDebugger,
6222 boolean persistent) {
6223 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6224 "setDebugApp()");
6225
6226 // Note that this is not really thread safe if there are multiple
6227 // callers into it at the same time, but that's not a situation we
6228 // care about.
6229 if (persistent) {
6230 final ContentResolver resolver = mContext.getContentResolver();
6231 Settings.System.putString(
6232 resolver, Settings.System.DEBUG_APP,
6233 packageName);
6234 Settings.System.putInt(
6235 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6236 waitForDebugger ? 1 : 0);
6237 }
6238
6239 synchronized (this) {
6240 if (!persistent) {
6241 mOrigDebugApp = mDebugApp;
6242 mOrigWaitForDebugger = mWaitForDebugger;
6243 }
6244 mDebugApp = packageName;
6245 mWaitForDebugger = waitForDebugger;
6246 mDebugTransient = !persistent;
6247 if (packageName != null) {
6248 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006249 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006250 Binder.restoreCallingIdentity(origId);
6251 }
6252 }
6253 }
6254
6255 public void setAlwaysFinish(boolean enabled) {
6256 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6257 "setAlwaysFinish()");
6258
6259 Settings.System.putInt(
6260 mContext.getContentResolver(),
6261 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6262
6263 synchronized (this) {
6264 mAlwaysFinishActivities = enabled;
6265 }
6266 }
6267
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006268 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006269 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006270 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006271 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006272 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006273 }
6274 }
6275
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006276 public boolean isUserAMonkey() {
6277 // For now the fact that there is a controller implies
6278 // we have a monkey.
6279 synchronized (this) {
6280 return mController != null;
6281 }
6282 }
6283
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006284 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006285 synchronized (this) {
6286 mWatchers.register(watcher);
6287 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006288 }
6289
6290 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006291 synchronized (this) {
6292 mWatchers.unregister(watcher);
6293 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006294 }
6295
Jeff Sharkeya4620792011-05-20 15:29:23 -07006296 public void registerProcessObserver(IProcessObserver observer) {
6297 mProcessObservers.register(observer);
6298 }
6299
6300 public void unregisterProcessObserver(IProcessObserver observer) {
6301 mProcessObservers.unregister(observer);
6302 }
6303
Daniel Sandler69a48172010-06-23 16:29:36 -04006304 public void setImmersive(IBinder token, boolean immersive) {
6305 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006306 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006307 if (index < 0) {
6308 throw new IllegalArgumentException();
6309 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006310 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006311 r.immersive = immersive;
6312 }
6313 }
6314
6315 public boolean isImmersive(IBinder token) {
6316 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006317 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006318 if (index < 0) {
6319 throw new IllegalArgumentException();
6320 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006321 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006322 return r.immersive;
6323 }
6324 }
6325
6326 public boolean isTopActivityImmersive() {
6327 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006328 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006329 return (r != null) ? r.immersive : false;
6330 }
6331 }
6332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006333 public final void enterSafeMode() {
6334 synchronized(this) {
6335 // It only makes sense to do this before the system is ready
6336 // and started launching other packages.
6337 if (!mSystemReady) {
6338 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006339 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006340 } catch (RemoteException e) {
6341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 }
6343 }
6344 }
6345
Jeff Brownb09abc12011-01-13 21:08:27 -08006346 public final void showSafeModeOverlay() {
6347 View v = LayoutInflater.from(mContext).inflate(
6348 com.android.internal.R.layout.safe_mode, null);
6349 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6350 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6351 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6352 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6353 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6354 lp.format = v.getBackground().getOpacity();
6355 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6356 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6357 ((WindowManager)mContext.getSystemService(
6358 Context.WINDOW_SERVICE)).addView(v, lp);
6359 }
6360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006361 public void noteWakeupAlarm(IIntentSender sender) {
6362 if (!(sender instanceof PendingIntentRecord)) {
6363 return;
6364 }
6365 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6366 synchronized (stats) {
6367 if (mBatteryStatsService.isOnBattery()) {
6368 mBatteryStatsService.enforceCallingPermission();
6369 PendingIntentRecord rec = (PendingIntentRecord)sender;
6370 int MY_UID = Binder.getCallingUid();
6371 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6372 BatteryStatsImpl.Uid.Pkg pkg =
6373 stats.getPackageStatsLocked(uid, rec.key.packageName);
6374 pkg.incWakeupsLocked();
6375 }
6376 }
6377 }
6378
Dianne Hackborn64825172011-03-02 21:32:58 -08006379 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006381 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006382 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006383 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 // XXX Note: don't acquire main activity lock here, because the window
6385 // manager calls in with its locks held.
6386
6387 boolean killed = false;
6388 synchronized (mPidsSelfLocked) {
6389 int[] types = new int[pids.length];
6390 int worstType = 0;
6391 for (int i=0; i<pids.length; i++) {
6392 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6393 if (proc != null) {
6394 int type = proc.setAdj;
6395 types[i] = type;
6396 if (type > worstType) {
6397 worstType = type;
6398 }
6399 }
6400 }
6401
Dianne Hackborn64825172011-03-02 21:32:58 -08006402 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006403 // then constrain it so we will kill all hidden procs.
6404 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6405 worstType = HIDDEN_APP_MIN_ADJ;
6406 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006407
6408 // If this is not a secure call, don't let it kill processes that
6409 // are important.
6410 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6411 worstType = SECONDARY_SERVER_ADJ;
6412 }
6413
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006414 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006415 for (int i=0; i<pids.length; i++) {
6416 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6417 if (proc == null) {
6418 continue;
6419 }
6420 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006421 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006422 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006423 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6424 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006425 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006426 proc.killedBackground = true;
6427 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006428 }
6429 }
6430 }
6431 return killed;
6432 }
6433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006434 public final void startRunning(String pkg, String cls, String action,
6435 String data) {
6436 synchronized(this) {
6437 if (mStartRunning) {
6438 return;
6439 }
6440 mStartRunning = true;
6441 mTopComponent = pkg != null && cls != null
6442 ? new ComponentName(pkg, cls) : null;
6443 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6444 mTopData = data;
6445 if (!mSystemReady) {
6446 return;
6447 }
6448 }
6449
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006450 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451 }
6452
6453 private void retrieveSettings() {
6454 final ContentResolver resolver = mContext.getContentResolver();
6455 String debugApp = Settings.System.getString(
6456 resolver, Settings.System.DEBUG_APP);
6457 boolean waitForDebugger = Settings.System.getInt(
6458 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6459 boolean alwaysFinishActivities = Settings.System.getInt(
6460 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6461
6462 Configuration configuration = new Configuration();
6463 Settings.System.getConfiguration(resolver, configuration);
6464
6465 synchronized (this) {
6466 mDebugApp = mOrigDebugApp = debugApp;
6467 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6468 mAlwaysFinishActivities = alwaysFinishActivities;
6469 // This happens before any activities are started, so we can
6470 // change mConfiguration in-place.
6471 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006472 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006473 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006474 }
6475 }
6476
6477 public boolean testIsSystemReady() {
6478 // no need to synchronize(this) just to read & return the value
6479 return mSystemReady;
6480 }
6481
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006482 private static File getCalledPreBootReceiversFile() {
6483 File dataDir = Environment.getDataDirectory();
6484 File systemDir = new File(dataDir, "system");
6485 File fname = new File(systemDir, "called_pre_boots.dat");
6486 return fname;
6487 }
6488
6489 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6490 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6491 File file = getCalledPreBootReceiversFile();
6492 FileInputStream fis = null;
6493 try {
6494 fis = new FileInputStream(file);
6495 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6496 int vers = dis.readInt();
6497 String codename = dis.readUTF();
6498 if (vers == android.os.Build.VERSION.SDK_INT
6499 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6500 int num = dis.readInt();
6501 while (num > 0) {
6502 num--;
6503 String pkg = dis.readUTF();
6504 String cls = dis.readUTF();
6505 lastDoneReceivers.add(new ComponentName(pkg, cls));
6506 }
6507 }
6508 } catch (FileNotFoundException e) {
6509 } catch (IOException e) {
6510 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6511 } finally {
6512 if (fis != null) {
6513 try {
6514 fis.close();
6515 } catch (IOException e) {
6516 }
6517 }
6518 }
6519 return lastDoneReceivers;
6520 }
6521
6522 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6523 File file = getCalledPreBootReceiversFile();
6524 FileOutputStream fos = null;
6525 DataOutputStream dos = null;
6526 try {
6527 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6528 fos = new FileOutputStream(file);
6529 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6530 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6531 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6532 dos.writeInt(list.size());
6533 for (int i=0; i<list.size(); i++) {
6534 dos.writeUTF(list.get(i).getPackageName());
6535 dos.writeUTF(list.get(i).getClassName());
6536 }
6537 } catch (IOException e) {
6538 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6539 file.delete();
6540 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006541 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006542 if (dos != null) {
6543 try {
6544 dos.close();
6545 } catch (IOException e) {
6546 // TODO Auto-generated catch block
6547 e.printStackTrace();
6548 }
6549 }
6550 }
6551 }
6552
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006553 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006554 // In the simulator, startRunning will never have been called, which
6555 // normally sets a few crucial variables. Do it here instead.
6556 if (!Process.supportsProcesses()) {
6557 mStartRunning = true;
6558 mTopAction = Intent.ACTION_MAIN;
6559 }
6560
6561 synchronized(this) {
6562 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006563 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 return;
6565 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006566
6567 // Check to see if there are any update receivers to run.
6568 if (!mDidUpdate) {
6569 if (mWaitingUpdate) {
6570 return;
6571 }
6572 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6573 List<ResolveInfo> ris = null;
6574 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006575 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006576 intent, null, 0);
6577 } catch (RemoteException e) {
6578 }
6579 if (ris != null) {
6580 for (int i=ris.size()-1; i>=0; i--) {
6581 if ((ris.get(i).activityInfo.applicationInfo.flags
6582 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6583 ris.remove(i);
6584 }
6585 }
6586 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006587
6588 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6589
6590 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006591 for (int i=0; i<ris.size(); i++) {
6592 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006593 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6594 if (lastDoneReceivers.contains(comp)) {
6595 ris.remove(i);
6596 i--;
6597 }
6598 }
6599
6600 for (int i=0; i<ris.size(); i++) {
6601 ActivityInfo ai = ris.get(i).activityInfo;
6602 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6603 doneReceivers.add(comp);
6604 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006605 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006606 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006607 finisher = new IIntentReceiver.Stub() {
6608 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006609 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006610 boolean sticky) {
6611 // The raw IIntentReceiver interface is called
6612 // with the AM lock held, so redispatch to
6613 // execute our code without the lock.
6614 mHandler.post(new Runnable() {
6615 public void run() {
6616 synchronized (ActivityManagerService.this) {
6617 mDidUpdate = true;
6618 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006619 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006620 systemReady(goingCallback);
6621 }
6622 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006623 }
6624 };
6625 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006626 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006627 broadcastIntentLocked(null, null, intent, null, finisher,
6628 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006629 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006630 mWaitingUpdate = true;
6631 }
6632 }
6633 }
6634 if (mWaitingUpdate) {
6635 return;
6636 }
6637 mDidUpdate = true;
6638 }
6639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006640 mSystemReady = true;
6641 if (!mStartRunning) {
6642 return;
6643 }
6644 }
6645
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006646 ArrayList<ProcessRecord> procsToKill = null;
6647 synchronized(mPidsSelfLocked) {
6648 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6649 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6650 if (!isAllowedWhileBooting(proc.info)){
6651 if (procsToKill == null) {
6652 procsToKill = new ArrayList<ProcessRecord>();
6653 }
6654 procsToKill.add(proc);
6655 }
6656 }
6657 }
6658
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006659 synchronized(this) {
6660 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006661 for (int i=procsToKill.size()-1; i>=0; i--) {
6662 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006663 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006664 removeProcessLocked(proc, true);
6665 }
6666 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006667
6668 // Now that we have cleaned up any update processes, we
6669 // are ready to start launching real processes and know that
6670 // we won't trample on them any more.
6671 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006672 }
6673
Joe Onorato8a9b2202010-02-26 18:56:32 -08006674 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006675 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006676 SystemClock.uptimeMillis());
6677
6678 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006679 // Make sure we have no pre-ready processes sitting around.
6680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006681 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6682 ResolveInfo ri = mContext.getPackageManager()
6683 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006684 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006685 CharSequence errorMsg = null;
6686 if (ri != null) {
6687 ActivityInfo ai = ri.activityInfo;
6688 ApplicationInfo app = ai.applicationInfo;
6689 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6690 mTopAction = Intent.ACTION_FACTORY_TEST;
6691 mTopData = null;
6692 mTopComponent = new ComponentName(app.packageName,
6693 ai.name);
6694 } else {
6695 errorMsg = mContext.getResources().getText(
6696 com.android.internal.R.string.factorytest_not_system);
6697 }
6698 } else {
6699 errorMsg = mContext.getResources().getText(
6700 com.android.internal.R.string.factorytest_no_action);
6701 }
6702 if (errorMsg != null) {
6703 mTopAction = null;
6704 mTopData = null;
6705 mTopComponent = null;
6706 Message msg = Message.obtain();
6707 msg.what = SHOW_FACTORY_ERROR_MSG;
6708 msg.getData().putCharSequence("msg", errorMsg);
6709 mHandler.sendMessage(msg);
6710 }
6711 }
6712 }
6713
6714 retrieveSettings();
6715
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006716 if (goingCallback != null) goingCallback.run();
6717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006718 synchronized (this) {
6719 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6720 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006721 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006722 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006723 if (apps != null) {
6724 int N = apps.size();
6725 int i;
6726 for (i=0; i<N; i++) {
6727 ApplicationInfo info
6728 = (ApplicationInfo)apps.get(i);
6729 if (info != null &&
6730 !info.packageName.equals("android")) {
6731 addAppLocked(info);
6732 }
6733 }
6734 }
6735 } catch (RemoteException ex) {
6736 // pm is in same process, this will never happen.
6737 }
6738 }
6739
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006740 // Start up initial activity.
6741 mBooting = true;
6742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006743 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006744 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006745 Message msg = Message.obtain();
6746 msg.what = SHOW_UID_ERROR_MSG;
6747 mHandler.sendMessage(msg);
6748 }
6749 } catch (RemoteException e) {
6750 }
6751
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006752 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006753 }
6754 }
6755
Dan Egnorb7f03672009-12-09 16:22:32 -08006756 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006757 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006758 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006759 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006760 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006761 startAppProblemLocked(app);
6762 app.stopFreezingAllLocked();
6763 return handleAppCrashLocked(app);
6764 }
6765
Dan Egnorb7f03672009-12-09 16:22:32 -08006766 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006767 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006768 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006769 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006770 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6771 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006772 startAppProblemLocked(app);
6773 app.stopFreezingAllLocked();
6774 }
6775
6776 /**
6777 * Generate a process error record, suitable for attachment to a ProcessRecord.
6778 *
6779 * @param app The ProcessRecord in which the error occurred.
6780 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6781 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006782 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006783 * @param shortMsg Short message describing the crash.
6784 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006785 * @param stackTrace Full crash stack trace, may be null.
6786 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006787 * @return Returns a fully-formed AppErrorStateInfo record.
6788 */
6789 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006790 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006791 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006793 report.condition = condition;
6794 report.processName = app.processName;
6795 report.pid = app.pid;
6796 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006797 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006798 report.shortMsg = shortMsg;
6799 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006800 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006801
6802 return report;
6803 }
6804
Dan Egnor42471dd2010-01-07 17:25:22 -08006805 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006806 synchronized (this) {
6807 app.crashing = false;
6808 app.crashingReport = null;
6809 app.notResponding = false;
6810 app.notRespondingReport = null;
6811 if (app.anrDialog == fromDialog) {
6812 app.anrDialog = null;
6813 }
6814 if (app.waitDialog == fromDialog) {
6815 app.waitDialog = null;
6816 }
6817 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006818 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006819 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07006820 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6821 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006822 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006824 }
6825 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006826
Dan Egnorb7f03672009-12-09 16:22:32 -08006827 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006828 long now = SystemClock.uptimeMillis();
6829
6830 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6831 app.info.uid);
6832 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6833 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006834 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006835 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006836 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006837 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006838 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6839 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006840 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006841 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006842 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006843 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006844 }
6845 }
6846 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006847 // Don't let services in this process be restarted and potentially
6848 // annoy the user repeatedly. Unless it is persistent, since those
6849 // processes run critical code.
6850 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006851 // We don't want to start this process again until the user
6852 // explicitly does so... but for persistent process, we really
6853 // need to keep it running. If a persistent process is actually
6854 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006855 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006856 app.info.processName);
6857 mBadProcesses.put(app.info.processName, app.info.uid, now);
6858 app.bad = true;
6859 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6860 app.removed = true;
6861 removeProcessLocked(app, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006862 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006863 return false;
6864 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006865 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006866 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006867 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006868 if (r.app == app) {
6869 // If the top running activity is from this crashing
6870 // process, then terminate it to avoid getting in a loop.
6871 Slog.w(TAG, " Force finishing activity "
6872 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006873 int index = mMainStack.indexOfTokenLocked(r);
6874 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006875 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006876 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006877 // stopped, to avoid a situation where one will get
6878 // re-start our crashing activity once it gets resumed again.
6879 index--;
6880 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006881 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006882 if (r.state == ActivityState.RESUMED
6883 || r.state == ActivityState.PAUSING
6884 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006885 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006886 Slog.w(TAG, " Force finishing activity "
6887 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006888 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006889 Activity.RESULT_CANCELED, null, "crashed");
6890 }
6891 }
6892 }
6893 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006894 }
6895
6896 // Bump up the crash count of any services currently running in the proc.
6897 if (app.services.size() != 0) {
6898 // Any services running in the application need to be placed
6899 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006900 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006901 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006902 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006903 sr.crashCount++;
6904 }
6905 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006906
6907 // If the crashing process is what we consider to be the "home process" and it has been
6908 // replaced by a third-party app, clear the package preferred activities from packages
6909 // with a home activity running in the process to prevent a repeatedly crashing app
6910 // from blocking the user to manually clear the list.
6911 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6912 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6913 Iterator it = mHomeProcess.activities.iterator();
6914 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006915 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006916 if (r.isHomeActivity) {
6917 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6918 try {
6919 ActivityThread.getPackageManager()
6920 .clearPackagePreferredActivities(r.packageName);
6921 } catch (RemoteException c) {
6922 // pm is in same process, this will never happen.
6923 }
6924 }
6925 }
6926 }
6927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006928 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6929 return true;
6930 }
6931
6932 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006933 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6934 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006935 skipCurrentReceiverLocked(app);
6936 }
6937
6938 void skipCurrentReceiverLocked(ProcessRecord app) {
6939 boolean reschedule = false;
6940 BroadcastRecord r = app.curReceiver;
6941 if (r != null) {
6942 // The current broadcast is waiting for this app's receiver
6943 // to be finished. Looks like that's not going to happen, so
6944 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006945 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006946 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6947 r.resultExtras, r.resultAbort, true);
6948 reschedule = true;
6949 }
6950 r = mPendingBroadcast;
6951 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006952 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006953 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006954 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006955 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6956 r.resultExtras, r.resultAbort, true);
6957 reschedule = true;
6958 }
6959 if (reschedule) {
6960 scheduleBroadcastsLocked();
6961 }
6962 }
6963
Dan Egnor60d87622009-12-16 16:32:58 -08006964 /**
6965 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6966 * The application process will exit immediately after this call returns.
6967 * @param app object of the crashing app, null for the system server
6968 * @param crashInfo describing the exception
6969 */
6970 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006971 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08006972
6973 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6974 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006975 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006976 crashInfo.exceptionClassName,
6977 crashInfo.exceptionMessage,
6978 crashInfo.throwFileName,
6979 crashInfo.throwLineNumber);
6980
Dan Egnor42471dd2010-01-07 17:25:22 -08006981 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006982
6983 crashApplication(r, crashInfo);
6984 }
6985
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006986 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006987 IBinder app,
6988 int violationMask,
6989 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006990 ProcessRecord r = findAppProcess(app, "StrictMode");
6991 if (r == null) {
6992 return;
6993 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006994
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006995 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006996 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006997 boolean logIt = true;
6998 synchronized (mAlreadyLoggedViolatedStacks) {
6999 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
7000 logIt = false;
7001 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007002 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007003 // the relative pain numbers, without logging all
7004 // the stack traces repeatedly. We'd want to do
7005 // likewise in the client code, which also does
7006 // dup suppression, before the Binder call.
7007 } else {
7008 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
7009 mAlreadyLoggedViolatedStacks.clear();
7010 }
7011 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
7012 }
7013 }
7014 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007015 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007016 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007017 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007018
7019 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
7020 AppErrorResult result = new AppErrorResult();
7021 synchronized (this) {
7022 final long origId = Binder.clearCallingIdentity();
7023
7024 Message msg = Message.obtain();
7025 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7026 HashMap<String, Object> data = new HashMap<String, Object>();
7027 data.put("result", result);
7028 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007029 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007030 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007031 msg.obj = data;
7032 mHandler.sendMessage(msg);
7033
7034 Binder.restoreCallingIdentity(origId);
7035 }
7036 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007037 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007038 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007039 }
7040
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007041 // Depending on the policy in effect, there could be a bunch of
7042 // these in quick succession so we try to batch these together to
7043 // minimize disk writes, number of dropbox entries, and maximize
7044 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007045 private void logStrictModeViolationToDropBox(
7046 ProcessRecord process,
7047 StrictMode.ViolationInfo info) {
7048 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007049 return;
7050 }
7051 final boolean isSystemApp = process == null ||
7052 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7053 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
7054 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7055 final DropBoxManager dbox = (DropBoxManager)
7056 mContext.getSystemService(Context.DROPBOX_SERVICE);
7057
7058 // Exit early if the dropbox isn't configured to accept this report type.
7059 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7060
7061 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007062 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007063 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7064 synchronized (sb) {
7065 bufferWasEmpty = sb.length() == 0;
7066 appendDropBoxProcessHeaders(process, sb);
7067 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7068 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007069 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7070 if (info.violationNumThisLoop != 0) {
7071 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7072 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007073 if (info.numAnimationsRunning != 0) {
7074 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7075 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007076 if (info.broadcastIntentAction != null) {
7077 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7078 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007079 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007080 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007081 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007082 if (info.numInstances != -1) {
7083 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7084 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007085 if (info.tags != null) {
7086 for (String tag : info.tags) {
7087 sb.append("Span-Tag: ").append(tag).append("\n");
7088 }
7089 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007090 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007091 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7092 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007093 }
7094 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007095
7096 // Only buffer up to ~64k. Various logging bits truncate
7097 // things at 128k.
7098 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007099 }
7100
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007101 // Flush immediately if the buffer's grown too large, or this
7102 // is a non-system app. Non-system apps are isolated with a
7103 // different tag & policy and not batched.
7104 //
7105 // Batching is useful during internal testing with
7106 // StrictMode settings turned up high. Without batching,
7107 // thousands of separate files could be created on boot.
7108 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007109 new Thread("Error dump: " + dropboxTag) {
7110 @Override
7111 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007112 String report;
7113 synchronized (sb) {
7114 report = sb.toString();
7115 sb.delete(0, sb.length());
7116 sb.trimToSize();
7117 }
7118 if (report.length() != 0) {
7119 dbox.addText(dropboxTag, report);
7120 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007121 }
7122 }.start();
7123 return;
7124 }
7125
7126 // System app batching:
7127 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007128 // An existing dropbox-writing thread is outstanding, so
7129 // we don't need to start it up. The existing thread will
7130 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007131 return;
7132 }
7133
7134 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7135 // (After this point, we shouldn't access AMS internal data structures.)
7136 new Thread("Error dump: " + dropboxTag) {
7137 @Override
7138 public void run() {
7139 // 5 second sleep to let stacks arrive and be batched together
7140 try {
7141 Thread.sleep(5000); // 5 seconds
7142 } catch (InterruptedException e) {}
7143
7144 String errorReport;
7145 synchronized (mStrictModeBuffer) {
7146 errorReport = mStrictModeBuffer.toString();
7147 if (errorReport.length() == 0) {
7148 return;
7149 }
7150 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7151 mStrictModeBuffer.trimToSize();
7152 }
7153 dbox.addText(dropboxTag, errorReport);
7154 }
7155 }.start();
7156 }
7157
Dan Egnor60d87622009-12-16 16:32:58 -08007158 /**
7159 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7160 * @param app object of the crashing app, null for the system server
7161 * @param tag reported by the caller
7162 * @param crashInfo describing the context of the error
7163 * @return true if the process should exit immediately (WTF is fatal)
7164 */
7165 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007166 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007167 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007168
7169 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7170 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007171 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007172 tag, crashInfo.exceptionMessage);
7173
Dan Egnor42471dd2010-01-07 17:25:22 -08007174 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007175
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007176 if (r != null && r.pid != Process.myPid() &&
7177 Settings.Secure.getInt(mContext.getContentResolver(),
7178 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007179 crashApplication(r, crashInfo);
7180 return true;
7181 } else {
7182 return false;
7183 }
7184 }
7185
7186 /**
7187 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7188 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7189 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007190 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007191 if (app == null) {
7192 return null;
7193 }
7194
7195 synchronized (this) {
7196 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7197 final int NA = apps.size();
7198 for (int ia=0; ia<NA; ia++) {
7199 ProcessRecord p = apps.valueAt(ia);
7200 if (p.thread != null && p.thread.asBinder() == app) {
7201 return p;
7202 }
7203 }
7204 }
7205
Dianne Hackborncb44d962011-03-10 17:02:27 -08007206 Slog.w(TAG, "Can't find mystery application for " + reason
7207 + " from pid=" + Binder.getCallingPid()
7208 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007209 return null;
7210 }
7211 }
7212
7213 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007214 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7215 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007216 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007217 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007218 // Watchdog thread ends up invoking this function (with
7219 // a null ProcessRecord) to add the stack file to dropbox.
7220 // Do not acquire a lock on this (am) in such cases, as it
7221 // could cause a potential deadlock, if and when watchdog
7222 // is invoked due to unavailability of lock on am and it
7223 // would prevent watchdog from killing system_server.
7224 if (process == null) {
7225 sb.append("Process: system_server\n");
7226 return;
7227 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007228 // Note: ProcessRecord 'process' is guarded by the service
7229 // instance. (notably process.pkgList, which could otherwise change
7230 // concurrently during execution of this method)
7231 synchronized (this) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007232 if (process.pid == MY_PID) {
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007233 sb.append("Process: system_server\n");
7234 } else {
7235 sb.append("Process: ").append(process.processName).append("\n");
7236 }
Dan Egnora455d192010-03-12 08:52:28 -08007237 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007238 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007239 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7240 for (String pkg : process.pkgList) {
7241 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007242 try {
Dan Egnora455d192010-03-12 08:52:28 -08007243 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7244 if (pi != null) {
7245 sb.append(" v").append(pi.versionCode);
7246 if (pi.versionName != null) {
7247 sb.append(" (").append(pi.versionName).append(")");
7248 }
7249 }
7250 } catch (RemoteException e) {
7251 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007252 }
Dan Egnora455d192010-03-12 08:52:28 -08007253 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007254 }
Dan Egnora455d192010-03-12 08:52:28 -08007255 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007256 }
7257
7258 private static String processClass(ProcessRecord process) {
7259 if (process == null || process.pid == MY_PID) {
7260 return "system_server";
7261 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7262 return "system_app";
7263 } else {
7264 return "data_app";
7265 }
7266 }
7267
7268 /**
7269 * Write a description of an error (crash, WTF, ANR) to the drop box.
7270 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7271 * @param process which caused the error, null means the system server
7272 * @param activity which triggered the error, null if unknown
7273 * @param parent activity related to the error, null if unknown
7274 * @param subject line related to the error, null if absent
7275 * @param report in long form describing the error, null if absent
7276 * @param logFile to include in the report, null if none
7277 * @param crashInfo giving an application stack trace, null if absent
7278 */
7279 public void addErrorToDropBox(String eventType,
7280 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7281 final String report, final File logFile,
7282 final ApplicationErrorReport.CrashInfo crashInfo) {
7283 // NOTE -- this must never acquire the ActivityManagerService lock,
7284 // otherwise the watchdog may be prevented from resetting the system.
7285
7286 final String dropboxTag = processClass(process) + "_" + eventType;
7287 final DropBoxManager dbox = (DropBoxManager)
7288 mContext.getSystemService(Context.DROPBOX_SERVICE);
7289
7290 // Exit early if the dropbox isn't configured to accept this report type.
7291 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7292
7293 final StringBuilder sb = new StringBuilder(1024);
7294 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007295 if (activity != null) {
7296 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7297 }
7298 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7299 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7300 }
7301 if (parent != null && parent != activity) {
7302 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7303 }
7304 if (subject != null) {
7305 sb.append("Subject: ").append(subject).append("\n");
7306 }
7307 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007308 if (Debug.isDebuggerConnected()) {
7309 sb.append("Debugger: Connected\n");
7310 }
Dan Egnora455d192010-03-12 08:52:28 -08007311 sb.append("\n");
7312
7313 // Do the rest in a worker thread to avoid blocking the caller on I/O
7314 // (After this point, we shouldn't access AMS internal data structures.)
7315 Thread worker = new Thread("Error dump: " + dropboxTag) {
7316 @Override
7317 public void run() {
7318 if (report != null) {
7319 sb.append(report);
7320 }
7321 if (logFile != null) {
7322 try {
7323 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7324 } catch (IOException e) {
7325 Slog.e(TAG, "Error reading " + logFile, e);
7326 }
7327 }
7328 if (crashInfo != null && crashInfo.stackTrace != null) {
7329 sb.append(crashInfo.stackTrace);
7330 }
7331
7332 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7333 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7334 if (lines > 0) {
7335 sb.append("\n");
7336
7337 // Merge several logcat streams, and take the last N lines
7338 InputStreamReader input = null;
7339 try {
7340 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7341 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7342 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7343
7344 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7345 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7346 input = new InputStreamReader(logcat.getInputStream());
7347
7348 int num;
7349 char[] buf = new char[8192];
7350 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7351 } catch (IOException e) {
7352 Slog.e(TAG, "Error running logcat", e);
7353 } finally {
7354 if (input != null) try { input.close(); } catch (IOException e) {}
7355 }
7356 }
7357
7358 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007359 }
Dan Egnora455d192010-03-12 08:52:28 -08007360 };
7361
7362 if (process == null || process.pid == MY_PID) {
7363 worker.run(); // We may be about to die -- need to run this synchronously
7364 } else {
7365 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007366 }
7367 }
7368
7369 /**
7370 * Bring up the "unexpected error" dialog box for a crashing app.
7371 * Deal with edge cases (intercepts from instrumented applications,
7372 * ActivityController, error intent receivers, that sort of thing).
7373 * @param r the application crashing
7374 * @param crashInfo describing the failure
7375 */
7376 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007377 long timeMillis = System.currentTimeMillis();
7378 String shortMsg = crashInfo.exceptionClassName;
7379 String longMsg = crashInfo.exceptionMessage;
7380 String stackTrace = crashInfo.stackTrace;
7381 if (shortMsg != null && longMsg != null) {
7382 longMsg = shortMsg + ": " + longMsg;
7383 } else if (shortMsg != null) {
7384 longMsg = shortMsg;
7385 }
7386
Dan Egnor60d87622009-12-16 16:32:58 -08007387 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007388 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007389 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 try {
7391 String name = r != null ? r.processName : null;
7392 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007393 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007394 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007395 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007396 + " at watcher's request");
7397 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007398 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007399 }
7400 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007401 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007402 }
7403 }
7404
7405 final long origId = Binder.clearCallingIdentity();
7406
7407 // If this process is running instrumentation, finish it.
7408 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007409 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007410 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007411 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7412 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007413 Bundle info = new Bundle();
7414 info.putString("shortMsg", shortMsg);
7415 info.putString("longMsg", longMsg);
7416 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7417 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007418 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419 }
7420
Dan Egnor60d87622009-12-16 16:32:58 -08007421 // If we can't identify the process or it's already exceeded its crash quota,
7422 // quit right away without showing a crash dialog.
7423 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007424 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007425 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007426 }
7427
7428 Message msg = Message.obtain();
7429 msg.what = SHOW_ERROR_MSG;
7430 HashMap data = new HashMap();
7431 data.put("result", result);
7432 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007433 msg.obj = data;
7434 mHandler.sendMessage(msg);
7435
7436 Binder.restoreCallingIdentity(origId);
7437 }
7438
7439 int res = result.get();
7440
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007441 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007442 synchronized (this) {
7443 if (r != null) {
7444 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7445 SystemClock.uptimeMillis());
7446 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007447 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007448 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007449 }
7450 }
7451
7452 if (appErrorIntent != null) {
7453 try {
7454 mContext.startActivity(appErrorIntent);
7455 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007456 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007459 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007460
7461 Intent createAppErrorIntentLocked(ProcessRecord r,
7462 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7463 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007464 if (report == null) {
7465 return null;
7466 }
7467 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7468 result.setComponent(r.errorReportReceiver);
7469 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7470 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7471 return result;
7472 }
7473
Dan Egnorb7f03672009-12-09 16:22:32 -08007474 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7475 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007476 if (r.errorReportReceiver == null) {
7477 return null;
7478 }
7479
7480 if (!r.crashing && !r.notResponding) {
7481 return null;
7482 }
7483
Dan Egnorb7f03672009-12-09 16:22:32 -08007484 ApplicationErrorReport report = new ApplicationErrorReport();
7485 report.packageName = r.info.packageName;
7486 report.installerPackageName = r.errorReportReceiver.getPackageName();
7487 report.processName = r.processName;
7488 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007489 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007490
Dan Egnorb7f03672009-12-09 16:22:32 -08007491 if (r.crashing) {
7492 report.type = ApplicationErrorReport.TYPE_CRASH;
7493 report.crashInfo = crashInfo;
7494 } else if (r.notResponding) {
7495 report.type = ApplicationErrorReport.TYPE_ANR;
7496 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007497
Dan Egnorb7f03672009-12-09 16:22:32 -08007498 report.anrInfo.activity = r.notRespondingReport.tag;
7499 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7500 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007501 }
7502
Dan Egnorb7f03672009-12-09 16:22:32 -08007503 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007504 }
7505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007506 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7507 // assume our apps are happy - lazy create the list
7508 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7509
7510 synchronized (this) {
7511
7512 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007513 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7514 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7516 // This one's in trouble, so we'll generate a report for it
7517 // crashes are higher priority (in case there's a crash *and* an anr)
7518 ActivityManager.ProcessErrorStateInfo report = null;
7519 if (app.crashing) {
7520 report = app.crashingReport;
7521 } else if (app.notResponding) {
7522 report = app.notRespondingReport;
7523 }
7524
7525 if (report != null) {
7526 if (errList == null) {
7527 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7528 }
7529 errList.add(report);
7530 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007531 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007532 " crashing = " + app.crashing +
7533 " notResponding = " + app.notResponding);
7534 }
7535 }
7536 }
7537 }
7538
7539 return errList;
7540 }
7541
7542 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7543 // Lazy instantiation of list
7544 List<ActivityManager.RunningAppProcessInfo> runList = null;
7545 synchronized (this) {
7546 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007547 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7548 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7550 // Generate process state info for running application
7551 ActivityManager.RunningAppProcessInfo currApp =
7552 new ActivityManager.RunningAppProcessInfo(app.processName,
7553 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007554 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007555 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007556 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007557 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007558 if (app.persistent) {
7559 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007561 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007562 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007563 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7564 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7565 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007566 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7567 } else if (adj >= HOME_APP_ADJ) {
7568 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7569 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 } else if (adj >= SECONDARY_SERVER_ADJ) {
7571 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007572 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007573 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007574 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7575 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007576 } else if (adj >= VISIBLE_APP_ADJ) {
7577 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7578 } else {
7579 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7580 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007581 currApp.importanceReasonCode = app.adjTypeCode;
7582 if (app.adjSource instanceof ProcessRecord) {
7583 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007584 } else if (app.adjSource instanceof ActivityRecord) {
7585 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007586 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7587 }
7588 if (app.adjTarget instanceof ComponentName) {
7589 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7590 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007591 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007592 // + " lru=" + currApp.lru);
7593 if (runList == null) {
7594 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7595 }
7596 runList.add(currApp);
7597 }
7598 }
7599 }
7600 return runList;
7601 }
7602
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007603 public List<ApplicationInfo> getRunningExternalApplications() {
7604 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7605 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7606 if (runningApps != null && runningApps.size() > 0) {
7607 Set<String> extList = new HashSet<String>();
7608 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7609 if (app.pkgList != null) {
7610 for (String pkg : app.pkgList) {
7611 extList.add(pkg);
7612 }
7613 }
7614 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007615 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007616 for (String pkg : extList) {
7617 try {
7618 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7619 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7620 retList.add(info);
7621 }
7622 } catch (RemoteException e) {
7623 }
7624 }
7625 }
7626 return retList;
7627 }
7628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007629 @Override
7630 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007631 if (checkCallingPermission(android.Manifest.permission.DUMP)
7632 != PackageManager.PERMISSION_GRANTED) {
7633 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7634 + Binder.getCallingPid()
7635 + ", uid=" + Binder.getCallingUid()
7636 + " without permission "
7637 + android.Manifest.permission.DUMP);
7638 return;
7639 }
7640
7641 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007642 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007643
7644 int opti = 0;
7645 while (opti < args.length) {
7646 String opt = args[opti];
7647 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7648 break;
7649 }
7650 opti++;
7651 if ("-a".equals(opt)) {
7652 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007653 } else if ("-c".equals(opt)) {
7654 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007655 } else if ("-h".equals(opt)) {
7656 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007657 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007658 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007659 pw.println(" a[ctivities]: activity stack state");
7660 pw.println(" b[roadcasts]: broadcast state");
7661 pw.println(" i[ntents]: pending intent state");
7662 pw.println(" p[rocesses]: process state");
7663 pw.println(" o[om]: out of memory management");
7664 pw.println(" prov[iders]: content provider state");
7665 pw.println(" s[ervices]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007666 pw.println(" service [COMP_SPEC]: service client-side state");
7667 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
7668 pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),");
7669 pw.println(" a partial substring in a component name, an");
7670 pw.println(" ActivityRecord hex object identifier, or");
7671 pw.println(" \"all\" for all objects");
7672 pw.println(" -a: include all available server state.");
7673 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007674 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007675 } else {
7676 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007677 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007678 }
7679
7680 // Is the caller requesting to dump a particular piece of data?
7681 if (opti < args.length) {
7682 String cmd = args[opti];
7683 opti++;
7684 if ("activities".equals(cmd) || "a".equals(cmd)) {
7685 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007686 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007687 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007688 return;
7689 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7690 synchronized (this) {
7691 dumpBroadcastsLocked(fd, pw, args, opti, true);
7692 }
7693 return;
7694 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7695 synchronized (this) {
7696 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7697 }
7698 return;
7699 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7700 synchronized (this) {
7701 dumpProcessesLocked(fd, pw, args, opti, true);
7702 }
7703 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007704 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7705 synchronized (this) {
7706 dumpOomLocked(fd, pw, args, opti, true);
7707 }
7708 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007709 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7710 synchronized (this) {
7711 dumpProvidersLocked(fd, pw, args, opti, true);
7712 }
7713 return;
7714 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007715 String[] newArgs;
7716 String name;
7717 if (opti >= args.length) {
7718 name = null;
7719 newArgs = EMPTY_STRING_ARRAY;
7720 } else {
7721 name = args[opti];
7722 opti++;
7723 newArgs = new String[args.length - opti];
7724 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7725 }
7726 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7727 pw.println("No services match: " + name);
7728 pw.println("Use -h for help.");
7729 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007730 return;
7731 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7732 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007733 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007734 }
7735 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007736 } else {
7737 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007738 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7739 pw.println("Bad activity command, or no activities match: " + cmd);
7740 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007741 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007742 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007743 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007744 }
7745
7746 // No piece of data specified, dump everything.
7747 synchronized (this) {
7748 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007749 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007750 if (needSep) {
7751 pw.println(" ");
7752 }
7753 if (dumpAll) {
7754 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007755 }
7756 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7757 if (needSep) {
7758 pw.println(" ");
7759 }
7760 if (dumpAll) {
7761 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007762 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007763 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007764 if (needSep) {
7765 pw.println(" ");
7766 }
7767 if (dumpAll) {
7768 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007769 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007770 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007771 if (needSep) {
7772 pw.println(" ");
7773 }
7774 if (dumpAll) {
7775 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007776 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007777 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007778 if (needSep) {
7779 pw.println(" ");
7780 }
7781 if (dumpAll) {
7782 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007783 }
7784 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7785 }
7786 }
7787
7788 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007789 int opti, boolean dumpAll, boolean dumpClient) {
7790 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7791 pw.println(" Main stack:");
7792 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007793 pw.println(" ");
7794 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007795 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007796 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007798 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007799 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7800 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007801 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007802 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007803 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007804 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007805 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7806 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007807 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007808 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7809 pw.println(" ");
7810 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007811 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7812 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007813 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007814 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007815 pw.println(" ");
7816 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007817 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7818 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007820
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007821 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007822 if (mMainStack.mPausingActivity != null) {
7823 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7824 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007825 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007826 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007827 if (dumpAll) {
7828 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7829 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
7830 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007831
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007832 if (mRecentTasks.size() > 0) {
7833 pw.println();
7834 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007835
7836 final int N = mRecentTasks.size();
7837 for (int i=0; i<N; i++) {
7838 TaskRecord tr = mRecentTasks.get(i);
7839 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7840 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007841 if (dumpAll) {
7842 mRecentTasks.get(i).dump(pw, " ");
7843 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007844 }
7845 }
7846
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007847 if (dumpAll) {
7848 pw.println(" ");
7849 pw.println(" mCurTask: " + mCurTask);
7850 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007851
7852 return true;
7853 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007854
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007855 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7856 int opti, boolean dumpAll) {
7857 boolean needSep = false;
7858 int numPers = 0;
7859
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007860 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7861
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007862 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7864 final int NA = procs.size();
7865 for (int ia=0; ia<NA; ia++) {
7866 if (!needSep) {
7867 pw.println(" All known processes:");
7868 needSep = true;
7869 }
7870 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007871 pw.print(r.persistent ? " *PERS*" : " *APP*");
7872 pw.print(" UID "); pw.print(procs.keyAt(ia));
7873 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007874 r.dump(pw, " ");
7875 if (r.persistent) {
7876 numPers++;
7877 }
7878 }
7879 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007880 }
7881
7882 if (mLruProcesses.size() > 0) {
7883 if (needSep) pw.println(" ");
7884 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007885 pw.println(" Process LRU list (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007886 dumpProcessOomList(pw, this, mLruProcesses, " ",
7887 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007888 needSep = true;
7889 }
7890
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007891 if (dumpAll) {
7892 synchronized (mPidsSelfLocked) {
7893 if (mPidsSelfLocked.size() > 0) {
7894 if (needSep) pw.println(" ");
7895 needSep = true;
7896 pw.println(" PID mappings:");
7897 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7898 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7899 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
7900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901 }
7902 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007903 }
7904
7905 if (mForegroundProcesses.size() > 0) {
7906 if (needSep) pw.println(" ");
7907 needSep = true;
7908 pw.println(" Foreground Processes:");
7909 for (int i=0; i<mForegroundProcesses.size(); i++) {
7910 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7911 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007912 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007913 }
7914
7915 if (mPersistentStartingProcesses.size() > 0) {
7916 if (needSep) pw.println(" ");
7917 needSep = true;
7918 pw.println(" Persisent processes that are starting:");
7919 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007920 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007921 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007922
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007923 if (mStartingProcesses.size() > 0) {
7924 if (needSep) pw.println(" ");
7925 needSep = true;
7926 pw.println(" Processes that are starting:");
7927 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007928 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007930
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007931 if (mRemovedProcesses.size() > 0) {
7932 if (needSep) pw.println(" ");
7933 needSep = true;
7934 pw.println(" Processes that are being removed:");
7935 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007936 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007937 }
7938
7939 if (mProcessesOnHold.size() > 0) {
7940 if (needSep) pw.println(" ");
7941 needSep = true;
7942 pw.println(" Processes that are on old until the system is ready:");
7943 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007944 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946
Dianne Hackborn287952c2010-09-22 22:34:31 -07007947 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007948
7949 if (mProcessCrashTimes.getMap().size() > 0) {
7950 if (needSep) pw.println(" ");
7951 needSep = true;
7952 pw.println(" Time since processes crashed:");
7953 long now = SystemClock.uptimeMillis();
7954 for (Map.Entry<String, SparseArray<Long>> procs
7955 : mProcessCrashTimes.getMap().entrySet()) {
7956 SparseArray<Long> uids = procs.getValue();
7957 final int N = uids.size();
7958 for (int i=0; i<N; i++) {
7959 pw.print(" Process "); pw.print(procs.getKey());
7960 pw.print(" uid "); pw.print(uids.keyAt(i));
7961 pw.print(": last crashed ");
7962 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007963 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007964 }
7965 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007968 if (mBadProcesses.getMap().size() > 0) {
7969 if (needSep) pw.println(" ");
7970 needSep = true;
7971 pw.println(" Bad processes:");
7972 for (Map.Entry<String, SparseArray<Long>> procs
7973 : mBadProcesses.getMap().entrySet()) {
7974 SparseArray<Long> uids = procs.getValue();
7975 final int N = uids.size();
7976 for (int i=0; i<N; i++) {
7977 pw.print(" Bad process "); pw.print(procs.getKey());
7978 pw.print(" uid "); pw.print(uids.keyAt(i));
7979 pw.print(": crashed at time ");
7980 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007981 }
7982 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007984
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007985 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007986 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007987 if (mHeavyWeightProcess != null) {
7988 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7989 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007990 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007991 if (dumpAll) {
7992 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07007993 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07007994 pw.println(" mScreenCompatPackages:");
7995 for (Map.Entry<String, Integer> entry
7996 : mCompatModePackages.getPackages().entrySet()) {
7997 String pkg = entry.getKey();
7998 int mode = entry.getValue();
7999 pw.print(" "); pw.print(pkg); pw.print(": ");
8000 pw.print(mode); pw.println();
8001 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07008002 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008003 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008004 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
8005 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
8006 || mOrigWaitForDebugger) {
8007 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
8008 + " mDebugTransient=" + mDebugTransient
8009 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
8010 }
8011 if (mAlwaysFinishActivities || mController != null) {
8012 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
8013 + " mController=" + mController);
8014 }
8015 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008016 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008017 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008018 + " mProcessesReady=" + mProcessesReady
8019 + " mSystemReady=" + mSystemReady);
8020 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021 + " mBooted=" + mBooted
8022 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008023 pw.print(" mLastPowerCheckRealtime=");
8024 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
8025 pw.println("");
8026 pw.print(" mLastPowerCheckUptime=");
8027 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
8028 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008029 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8030 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008031 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008033
8034 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008035 }
8036
Dianne Hackborn287952c2010-09-22 22:34:31 -07008037 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
8038 int opti, boolean needSep, boolean dumpAll) {
8039 if (mProcessesToGc.size() > 0) {
8040 if (needSep) pw.println(" ");
8041 needSep = true;
8042 pw.println(" Processes that are waiting to GC:");
8043 long now = SystemClock.uptimeMillis();
8044 for (int i=0; i<mProcessesToGc.size(); i++) {
8045 ProcessRecord proc = mProcessesToGc.get(i);
8046 pw.print(" Process "); pw.println(proc);
8047 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8048 pw.print(", last gced=");
8049 pw.print(now-proc.lastRequestedGc);
8050 pw.print(" ms ago, last lowMem=");
8051 pw.print(now-proc.lastLowMemory);
8052 pw.println(" ms ago");
8053
8054 }
8055 }
8056 return needSep;
8057 }
8058
8059 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8060 int opti, boolean dumpAll) {
8061 boolean needSep = false;
8062
8063 if (mLruProcesses.size() > 0) {
8064 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
8065
8066 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
8067 @Override
8068 public int compare(ProcessRecord object1, ProcessRecord object2) {
8069 if (object1.setAdj != object2.setAdj) {
8070 return object1.setAdj > object2.setAdj ? -1 : 1;
8071 }
8072 if (object1.setSchedGroup != object2.setSchedGroup) {
8073 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
8074 }
8075 if (object1.keeping != object2.keeping) {
8076 return object1.keeping ? -1 : 1;
8077 }
8078 if (object1.pid != object2.pid) {
8079 return object1.pid > object2.pid ? -1 : 1;
8080 }
8081 return 0;
8082 }
8083 };
8084
8085 Collections.sort(procs, comparator);
8086
8087 if (needSep) pw.println(" ");
8088 needSep = true;
8089 pw.println(" Process OOM control:");
8090 dumpProcessOomList(pw, this, procs, " ",
8091 "Proc", "PERS", true);
8092 needSep = true;
8093 }
8094
8095 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
8096
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008097 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008098 pw.println(" mHomeProcess: " + mHomeProcess);
8099 if (mHeavyWeightProcess != null) {
8100 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8101 }
8102
8103 return true;
8104 }
8105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008106 /**
8107 * There are three ways to call this:
8108 * - no service specified: dump all the services
8109 * - a flattened component name that matched an existing service was specified as the
8110 * first arg: dump that one service
8111 * - the first arg isn't the flattened component name of an existing service:
8112 * dump all services whose component contains the first arg as a substring
8113 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008114 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8115 int opti, boolean dumpAll) {
8116 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008117
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008118 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008119 synchronized (this) {
8120 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008121 services.add(r1);
8122 }
8123 }
8124 } else {
8125 ComponentName componentName = name != null
8126 ? ComponentName.unflattenFromString(name) : null;
8127 int objectId = 0;
8128 if (componentName == null) {
8129 // Not a '/' separated full component name; maybe an object ID?
8130 try {
8131 objectId = Integer.parseInt(name, 16);
8132 name = null;
8133 componentName = null;
8134 } catch (RuntimeException e) {
8135 }
8136 }
8137
8138 synchronized (this) {
8139 for (ServiceRecord r1 : mServices.values()) {
8140 if (componentName != null) {
8141 if (r1.name.equals(componentName)) {
8142 services.add(r1);
8143 }
8144 } else if (name != null) {
8145 if (r1.name.flattenToString().contains(name)) {
8146 services.add(r1);
8147 }
8148 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008149 services.add(r1);
8150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008151 }
8152 }
8153 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008154
8155 if (services.size() <= 0) {
8156 return false;
8157 }
8158
8159 boolean needSep = false;
8160 for (int i=0; i<services.size(); i++) {
8161 if (needSep) {
8162 pw.println();
8163 }
8164 needSep = true;
8165 dumpService("", fd, pw, services.get(i), args, dumpAll);
8166 }
8167 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008168 }
8169
8170 /**
8171 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8172 * there is a thread associated with the service.
8173 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008174 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8175 final ServiceRecord r, String[] args, boolean dumpAll) {
8176 String innerPrefix = prefix + " ";
8177 synchronized (this) {
8178 pw.print(prefix); pw.print("SERVICE ");
8179 pw.print(r.shortName); pw.print(" ");
8180 pw.print(Integer.toHexString(System.identityHashCode(r)));
8181 pw.print(" pid=");
8182 if (r.app != null) pw.println(r.app.pid);
8183 else pw.println("(not running)");
8184 if (dumpAll) {
8185 r.dump(pw, innerPrefix);
8186 }
8187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008188 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008189 pw.print(prefix); pw.println(" Client:");
8190 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008191 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008192 TransferPipe tp = new TransferPipe();
8193 try {
8194 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8195 tp.setBufferPrefix(prefix + " ");
8196 tp.go(fd);
8197 } finally {
8198 tp.kill();
8199 }
8200 } catch (IOException e) {
8201 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008202 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008203 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008204 }
8205 }
8206 }
8207
Dianne Hackborn625ac272010-09-17 18:29:22 -07008208 /**
8209 * There are three things that cmd can be:
8210 * - a flattened component name that matched an existing activity
8211 * - the cmd arg isn't the flattened component name of an existing activity:
8212 * dump all activity whose component contains the cmd as a substring
8213 * - A hex number of the ActivityRecord object instance.
8214 */
8215 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8216 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008217 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008218
8219 if ("all".equals(name)) {
8220 synchronized (this) {
8221 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008222 activities.add(r1);
8223 }
8224 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008225 } else {
8226 ComponentName componentName = ComponentName.unflattenFromString(name);
8227 int objectId = 0;
8228 if (componentName == null) {
8229 // Not a '/' separated full component name; maybe an object ID?
8230 try {
8231 objectId = Integer.parseInt(name, 16);
8232 name = null;
8233 componentName = null;
8234 } catch (RuntimeException e) {
8235 }
8236 }
8237
8238 synchronized (this) {
8239 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
8240 if (componentName != null) {
8241 if (r1.intent.getComponent().equals(componentName)) {
8242 activities.add(r1);
8243 }
8244 } else if (name != null) {
8245 if (r1.intent.getComponent().flattenToString().contains(name)) {
8246 activities.add(r1);
8247 }
8248 } else if (System.identityHashCode(r1) == objectId) {
8249 activities.add(r1);
8250 }
8251 }
8252 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008253 }
8254
8255 if (activities.size() <= 0) {
8256 return false;
8257 }
8258
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008259 String[] newArgs = new String[args.length - opti];
8260 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8261
Dianne Hackborn30d71892010-12-11 10:37:55 -08008262 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008263 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008264 for (int i=activities.size()-1; i>=0; i--) {
8265 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008266 if (needSep) {
8267 pw.println();
8268 }
8269 needSep = true;
8270 synchronized (this) {
8271 if (lastTask != r.task) {
8272 lastTask = r.task;
8273 pw.print("TASK "); pw.print(lastTask.affinity);
8274 pw.print(" id="); pw.println(lastTask.taskId);
8275 if (dumpAll) {
8276 lastTask.dump(pw, " ");
8277 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008278 }
8279 }
8280 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008281 }
8282 return true;
8283 }
8284
8285 /**
8286 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8287 * there is a thread associated with the activity.
8288 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008289 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008290 final ActivityRecord r, String[] args, boolean dumpAll) {
8291 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008292 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008293 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8294 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8295 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008296 if (r.app != null) pw.println(r.app.pid);
8297 else pw.println("(not running)");
8298 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008299 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008300 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008301 }
8302 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008303 // flush anything that is already in the PrintWriter since the thread is going
8304 // to write to the file descriptor directly
8305 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008306 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008307 TransferPipe tp = new TransferPipe();
8308 try {
8309 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8310 innerPrefix, args);
8311 tp.go(fd);
8312 } finally {
8313 tp.kill();
8314 }
8315 } catch (IOException e) {
8316 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008317 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008318 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008319 }
8320 }
8321 }
8322
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008323 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8324 int opti, boolean dumpAll) {
8325 boolean needSep = false;
8326
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008327 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008328 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008329 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008330 pw.println(" Registered Receivers:");
8331 Iterator it = mRegisteredReceivers.values().iterator();
8332 while (it.hasNext()) {
8333 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008334 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 r.dump(pw, " ");
8336 }
8337 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008338
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008339 pw.println();
8340 pw.println(" Receiver Resolver Table:");
8341 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008342 needSep = true;
8343 }
8344
8345 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8346 || mPendingBroadcast != null) {
8347 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008348 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008349 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008350 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008351 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8352 pw.println(" Broadcast #" + i + ":");
8353 mParallelBroadcasts.get(i).dump(pw, " ");
8354 }
8355 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008356 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008357 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008358 }
8359 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8360 pw.println(" Serialized Broadcast #" + i + ":");
8361 mOrderedBroadcasts.get(i).dump(pw, " ");
8362 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008363 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008364 pw.println(" Pending broadcast:");
8365 if (mPendingBroadcast != null) {
8366 mPendingBroadcast.dump(pw, " ");
8367 } else {
8368 pw.println(" (null)");
8369 }
8370 needSep = true;
8371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008372
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008373 if (needSep) {
8374 pw.println();
8375 }
8376 pw.println(" Historical broadcasts:");
8377 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8378 BroadcastRecord r = mBroadcastHistory[i];
8379 if (r == null) {
8380 break;
8381 }
8382 if (dumpAll) {
8383 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8384 r.dump(pw, " ");
8385 } else {
8386 if (i >= 50) {
8387 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008388 break;
8389 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008390 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008391 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008392 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008393 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008394
8395 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008396 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008397 pw.println(" Sticky broadcasts:");
8398 StringBuilder sb = new StringBuilder(128);
8399 for (Map.Entry<String, ArrayList<Intent>> ent
8400 : mStickyBroadcasts.entrySet()) {
8401 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008402 if (dumpAll) {
8403 pw.println(":");
8404 ArrayList<Intent> intents = ent.getValue();
8405 final int N = intents.size();
8406 for (int i=0; i<N; i++) {
8407 sb.setLength(0);
8408 sb.append(" Intent: ");
8409 intents.get(i).toShortString(sb, true, false);
8410 pw.println(sb.toString());
8411 Bundle bundle = intents.get(i).getExtras();
8412 if (bundle != null) {
8413 pw.print(" ");
8414 pw.println(bundle.toString());
8415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008416 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008417 } else {
8418 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008419 }
8420 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008421 needSep = true;
8422 }
8423
8424 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008425 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008426 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008427 pw.println(" mHandler:");
8428 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008429 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008430 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008431
8432 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008433 }
8434
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008435 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008436 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008437 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008438
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008439 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8440 if (mServices.size() > 0) {
8441 pw.println(" Active services:");
8442 long nowReal = SystemClock.elapsedRealtime();
8443 Iterator<ServiceRecord> it = mServices.values().iterator();
8444 needSep = false;
8445 while (it.hasNext()) {
8446 ServiceRecord r = it.next();
8447 if (needSep) {
8448 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008449 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008450 pw.print(" * "); pw.println(r);
8451 if (dumpAll) {
8452 r.dump(pw, " ");
8453 needSep = true;
8454 } else {
8455 pw.print(" app="); pw.println(r.app);
8456 pw.print(" created=");
8457 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8458 pw.print(" started="); pw.print(r.startRequested);
8459 pw.print(" connections="); pw.println(r.connections.size());
8460 }
8461 if (dumpClient && r.app != null && r.app.thread != null) {
8462 pw.println(" Client:");
8463 pw.flush();
8464 try {
8465 TransferPipe tp = new TransferPipe();
8466 try {
8467 r.app.thread.dumpService(
8468 tp.getWriteFd().getFileDescriptor(), r, args);
8469 tp.setBufferPrefix(" ");
8470 // Short timeout, since blocking here can
8471 // deadlock with the application.
8472 tp.go(fd, 2000);
8473 } finally {
8474 tp.kill();
8475 }
8476 } catch (IOException e) {
8477 pw.println(" Failure while dumping the service: " + e);
8478 } catch (RemoteException e) {
8479 pw.println(" Got a RemoteException while dumping the service");
8480 }
8481 needSep = true;
8482 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008483 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008484 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008487 if (mPendingServices.size() > 0) {
8488 if (needSep) pw.println(" ");
8489 pw.println(" Pending services:");
8490 for (int i=0; i<mPendingServices.size(); i++) {
8491 ServiceRecord r = mPendingServices.get(i);
8492 pw.print(" * Pending "); pw.println(r);
8493 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008494 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008495 needSep = true;
8496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008497
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008498 if (mRestartingServices.size() > 0) {
8499 if (needSep) pw.println(" ");
8500 pw.println(" Restarting services:");
8501 for (int i=0; i<mRestartingServices.size(); i++) {
8502 ServiceRecord r = mRestartingServices.get(i);
8503 pw.print(" * Restarting "); pw.println(r);
8504 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008505 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008506 needSep = true;
8507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008508
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008509 if (mStoppingServices.size() > 0) {
8510 if (needSep) pw.println(" ");
8511 pw.println(" Stopping services:");
8512 for (int i=0; i<mStoppingServices.size(); i++) {
8513 ServiceRecord r = mStoppingServices.get(i);
8514 pw.print(" * Stopping "); pw.println(r);
8515 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008516 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008517 needSep = true;
8518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008519
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008520 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008521 if (mServiceConnections.size() > 0) {
8522 if (needSep) pw.println(" ");
8523 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008524 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008525 = mServiceConnections.values().iterator();
8526 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008527 ArrayList<ConnectionRecord> r = it.next();
8528 for (int i=0; i<r.size(); i++) {
8529 pw.print(" * "); pw.println(r.get(i));
8530 r.get(i).dump(pw, " ");
8531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008532 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008533 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008534 }
8535 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008536
8537 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008538 }
8539
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008540 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8541 int opti, boolean dumpAll) {
8542 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008543
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008544 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8545 if (mProvidersByClass.size() > 0) {
8546 if (needSep) pw.println(" ");
8547 pw.println(" Published content providers (by class):");
8548 Iterator<Map.Entry<String, ContentProviderRecord>> it
8549 = mProvidersByClass.entrySet().iterator();
8550 while (it.hasNext()) {
8551 Map.Entry<String, ContentProviderRecord> e = it.next();
8552 ContentProviderRecord r = e.getValue();
8553 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008554 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008556 } else {
8557 pw.print(" * "); pw.print(r.name.toShortString());
8558 if (r.app != null) {
8559 pw.println(":");
8560 pw.print(" "); pw.println(r.app);
8561 } else {
8562 pw.println();
8563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008564 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008565 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008566 needSep = true;
8567 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008568
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008569 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008570 if (mProvidersByName.size() > 0) {
8571 pw.println(" ");
8572 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008573 Iterator<Map.Entry<String, ContentProviderRecord>> it
8574 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008575 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008576 Map.Entry<String, ContentProviderRecord> e = it.next();
8577 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008578 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8579 pw.println(r);
8580 }
8581 needSep = true;
8582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008583 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008584
8585 if (mLaunchingProviders.size() > 0) {
8586 if (needSep) pw.println(" ");
8587 pw.println(" Launching content providers:");
8588 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8589 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8590 pw.println(mLaunchingProviders.get(i));
8591 }
8592 needSep = true;
8593 }
8594
8595 if (mGrantedUriPermissions.size() > 0) {
8596 pw.println();
8597 pw.println("Granted Uri Permissions:");
8598 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8599 int uid = mGrantedUriPermissions.keyAt(i);
8600 HashMap<Uri, UriPermission> perms
8601 = mGrantedUriPermissions.valueAt(i);
8602 pw.print(" * UID "); pw.print(uid);
8603 pw.println(" holds:");
8604 for (UriPermission perm : perms.values()) {
8605 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008606 if (dumpAll) {
8607 perm.dump(pw, " ");
8608 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008609 }
8610 }
8611 needSep = true;
8612 }
8613
8614 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008615 }
8616
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008617 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8618 int opti, boolean dumpAll) {
8619 boolean needSep = false;
8620
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008621 if (this.mIntentSenderRecords.size() > 0) {
8622 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8623 Iterator<WeakReference<PendingIntentRecord>> it
8624 = mIntentSenderRecords.values().iterator();
8625 while (it.hasNext()) {
8626 WeakReference<PendingIntentRecord> ref = it.next();
8627 PendingIntentRecord rec = ref != null ? ref.get(): null;
8628 needSep = true;
8629 if (rec != null) {
8630 pw.print(" * "); pw.println(rec);
8631 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008632 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008634 } else {
8635 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008636 }
8637 }
8638 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008639
8640 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008641 }
8642
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008643 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8644 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008645 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008646 boolean needNL = false;
8647 final String innerPrefix = prefix + " ";
8648 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008650 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008651 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008652 if (needNL) {
8653 pw.println(" ");
8654 needNL = false;
8655 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008656 if (lastTask != r.task) {
8657 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008658 pw.print(prefix);
8659 pw.print(full ? "* " : " ");
8660 pw.println(lastTask);
8661 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008662 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008663 } else if (complete) {
8664 // Complete + brief == give a summary. Isn't that obvious?!?
8665 if (lastTask.intent != null) {
8666 pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
8667 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008668 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008670 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8671 pw.print(" #"); pw.print(i); pw.print(": ");
8672 pw.println(r);
8673 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008674 r.dump(pw, innerPrefix);
8675 } else if (complete) {
8676 // Complete + brief == give a summary. Isn't that obvious?!?
8677 pw.print(innerPrefix); pw.println(r.intent);
8678 if (r.app != null) {
8679 pw.print(innerPrefix); pw.println(r.app);
8680 }
8681 }
8682 if (client && r.app != null && r.app.thread != null) {
8683 // flush anything that is already in the PrintWriter since the thread is going
8684 // to write to the file descriptor directly
8685 pw.flush();
8686 try {
8687 TransferPipe tp = new TransferPipe();
8688 try {
8689 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8690 innerPrefix, args);
8691 // Short timeout, since blocking here can
8692 // deadlock with the application.
8693 tp.go(fd, 2000);
8694 } finally {
8695 tp.kill();
8696 }
8697 } catch (IOException e) {
8698 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8699 } catch (RemoteException e) {
8700 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8701 }
8702 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008703 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008704 }
8705 }
8706
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008707 private static String buildOomTag(String prefix, String space, int val, int base) {
8708 if (val == base) {
8709 if (space == null) return prefix;
8710 return prefix + " ";
8711 }
8712 return prefix + "+" + Integer.toString(val-base);
8713 }
8714
8715 private static final int dumpProcessList(PrintWriter pw,
8716 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008717 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008718 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008719 final int N = list.size()-1;
8720 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008721 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008722 pw.println(String.format("%s%s #%2d: %s",
8723 prefix, (r.persistent ? persistentLabel : normalLabel),
8724 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008725 if (r.persistent) {
8726 numPers++;
8727 }
8728 }
8729 return numPers;
8730 }
8731
Dianne Hackborn287952c2010-09-22 22:34:31 -07008732 private static final void dumpProcessOomList(PrintWriter pw,
8733 ActivityManagerService service, List<ProcessRecord> list,
8734 String prefix, String normalLabel, String persistentLabel,
8735 boolean inclDetails) {
8736
8737 final long curRealtime = SystemClock.elapsedRealtime();
8738 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8739 final long curUptime = SystemClock.uptimeMillis();
8740 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8741
8742 final int N = list.size()-1;
8743 for (int i=N; i>=0; i--) {
8744 ProcessRecord r = list.get(i);
8745 String oomAdj;
8746 if (r.setAdj >= EMPTY_APP_ADJ) {
8747 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8748 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8749 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8750 } else if (r.setAdj >= HOME_APP_ADJ) {
8751 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8752 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8753 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8754 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8755 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8756 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8757 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8758 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8759 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8760 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8761 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8762 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8763 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8764 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8765 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8766 } else if (r.setAdj >= SYSTEM_ADJ) {
8767 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8768 } else {
8769 oomAdj = Integer.toString(r.setAdj);
8770 }
8771 String schedGroup;
8772 switch (r.setSchedGroup) {
8773 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8774 schedGroup = "B";
8775 break;
8776 case Process.THREAD_GROUP_DEFAULT:
8777 schedGroup = "F";
8778 break;
8779 default:
8780 schedGroup = Integer.toString(r.setSchedGroup);
8781 break;
8782 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008783 String foreground;
8784 if (r.foregroundActivities) {
8785 foreground = "A";
8786 } else if (r.foregroundServices) {
8787 foreground = "S";
8788 } else {
8789 foreground = " ";
8790 }
8791 pw.println(String.format("%s%s #%2d: adj=%s/%s%s %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008792 prefix, (r.persistent ? persistentLabel : normalLabel),
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008793 N-i, oomAdj, schedGroup, foreground, r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07008794 if (r.adjSource != null || r.adjTarget != null) {
8795 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008796 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008797 if (r.adjTarget instanceof ComponentName) {
8798 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8799 } else if (r.adjTarget != null) {
8800 pw.print(r.adjTarget.toString());
8801 } else {
8802 pw.print("{null}");
8803 }
8804 pw.print("<=");
8805 if (r.adjSource instanceof ProcessRecord) {
8806 pw.print("Proc{");
8807 pw.print(((ProcessRecord)r.adjSource).toShortString());
8808 pw.println("}");
8809 } else if (r.adjSource != null) {
8810 pw.println(r.adjSource.toString());
8811 } else {
8812 pw.println("{null}");
8813 }
8814 }
8815 if (inclDetails) {
8816 pw.print(prefix);
8817 pw.print(" ");
8818 pw.print("oom: max="); pw.print(r.maxAdj);
8819 pw.print(" hidden="); pw.print(r.hiddenAdj);
8820 pw.print(" curRaw="); pw.print(r.curRawAdj);
8821 pw.print(" setRaw="); pw.print(r.setRawAdj);
8822 pw.print(" cur="); pw.print(r.curAdj);
8823 pw.print(" set="); pw.println(r.setAdj);
8824 pw.print(prefix);
8825 pw.print(" ");
8826 pw.print("keeping="); pw.print(r.keeping);
8827 pw.print(" hidden="); pw.print(r.hidden);
8828 pw.print(" empty="); pw.println(r.empty);
8829
8830 if (!r.keeping) {
8831 if (r.lastWakeTime != 0) {
8832 long wtime;
8833 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8834 synchronized (stats) {
8835 wtime = stats.getProcessWakeTime(r.info.uid,
8836 r.pid, curRealtime);
8837 }
8838 long timeUsed = wtime - r.lastWakeTime;
8839 pw.print(prefix);
8840 pw.print(" ");
8841 pw.print("keep awake over ");
8842 TimeUtils.formatDuration(realtimeSince, pw);
8843 pw.print(" used ");
8844 TimeUtils.formatDuration(timeUsed, pw);
8845 pw.print(" (");
8846 pw.print((timeUsed*100)/realtimeSince);
8847 pw.println("%)");
8848 }
8849 if (r.lastCpuTime != 0) {
8850 long timeUsed = r.curCpuTime - r.lastCpuTime;
8851 pw.print(prefix);
8852 pw.print(" ");
8853 pw.print("run cpu over ");
8854 TimeUtils.formatDuration(uptimeSince, pw);
8855 pw.print(" used ");
8856 TimeUtils.formatDuration(timeUsed, pw);
8857 pw.print(" (");
8858 pw.print((timeUsed*100)/uptimeSince);
8859 pw.println("%)");
8860 }
8861 }
8862 }
8863 }
8864 }
8865
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008866 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
8867 ArrayList<ProcessRecord> procs;
8868 synchronized (this) {
8869 if (args != null && args.length > 0
8870 && args[0].charAt(0) != '-') {
8871 procs = new ArrayList<ProcessRecord>();
8872 int pid = -1;
8873 try {
8874 pid = Integer.parseInt(args[0]);
8875 } catch (NumberFormatException e) {
8876
8877 }
8878 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8879 ProcessRecord proc = mLruProcesses.get(i);
8880 if (proc.pid == pid) {
8881 procs.add(proc);
8882 } else if (proc.processName.equals(args[0])) {
8883 procs.add(proc);
8884 }
8885 }
8886 if (procs.size() <= 0) {
8887 pw.println("No process found for: " + args[0]);
8888 return null;
8889 }
8890 } else {
8891 procs = new ArrayList<ProcessRecord>(mLruProcesses);
8892 }
8893 }
8894 return procs;
8895 }
8896
8897 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
8898 PrintWriter pw, String[] args) {
8899 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8900 if (procs == null) {
8901 return;
8902 }
8903
8904 long uptime = SystemClock.uptimeMillis();
8905 long realtime = SystemClock.elapsedRealtime();
8906 pw.println("Applications Graphics Acceleration Info:");
8907 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8908
8909 String callArgs[] = {"graphics"};
8910 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8911 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008912 if (r.thread != null) {
8913 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
8914 pw.flush();
8915 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008916 TransferPipe.goDump(r.thread.asBinder(), fd, callArgs);
8917 } catch (IOException e) {
8918 pw.println("Failure: " + e);
8919 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07008920 } catch (RemoteException e) {
8921 pw.println("Got RemoteException!");
8922 pw.flush();
8923 }
8924 }
8925 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07008926 }
8927
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008928 final void dumpApplicationMemoryUsage(FileDescriptor fd,
8929 PrintWriter pw, String prefix, String[] args) {
8930 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8931 if (procs == null) {
8932 return;
8933 }
8934
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008935 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008936 long uptime = SystemClock.uptimeMillis();
8937 long realtime = SystemClock.elapsedRealtime();
8938
8939 if (isCheckinRequest) {
8940 // short checkin version
8941 pw.println(uptime + "," + realtime);
8942 pw.flush();
8943 } else {
8944 pw.println("Applications Memory Usage (kB):");
8945 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8946 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008947 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8948 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008949 if (r.thread != null) {
8950 if (!isCheckinRequest) {
8951 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8952 pw.flush();
8953 }
8954 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008955 TransferPipe.goDump(r.thread.asBinder(), fd, args);
8956 } catch (IOException e) {
8957 pw.println("Failure: " + e);
8958 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008959 } catch (RemoteException e) {
8960 if (!isCheckinRequest) {
8961 pw.println("Got RemoteException!");
8962 pw.flush();
8963 }
8964 }
8965 }
8966 }
8967 }
8968
8969 /**
8970 * Searches array of arguments for the specified string
8971 * @param args array of argument strings
8972 * @param value value to search for
8973 * @return true if the value is contained in the array
8974 */
8975 private static boolean scanArgs(String[] args, String value) {
8976 if (args != null) {
8977 for (String arg : args) {
8978 if (value.equals(arg)) {
8979 return true;
8980 }
8981 }
8982 }
8983 return false;
8984 }
8985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008986 private final void killServicesLocked(ProcessRecord app,
8987 boolean allowRestart) {
8988 // Report disconnected services.
8989 if (false) {
8990 // XXX we are letting the client link to the service for
8991 // death notifications.
8992 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008993 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008994 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008995 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008996 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008997 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998 = r.connections.values().iterator();
8999 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009000 ArrayList<ConnectionRecord> cl = jt.next();
9001 for (int i=0; i<cl.size(); i++) {
9002 ConnectionRecord c = cl.get(i);
9003 if (c.binding.client != app) {
9004 try {
9005 //c.conn.connected(r.className, null);
9006 } catch (Exception e) {
9007 // todo: this should be asynchronous!
9008 Slog.w(TAG, "Exception thrown disconnected servce "
9009 + r.shortName
9010 + " from app " + app.processName, e);
9011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009012 }
9013 }
9014 }
9015 }
9016 }
9017 }
9018 }
9019
9020 // Clean up any connections this application has to other services.
9021 if (app.connections.size() > 0) {
9022 Iterator<ConnectionRecord> it = app.connections.iterator();
9023 while (it.hasNext()) {
9024 ConnectionRecord r = it.next();
9025 removeConnectionLocked(r, app, null);
9026 }
9027 }
9028 app.connections.clear();
9029
9030 if (app.services.size() != 0) {
9031 // Any services running in the application need to be placed
9032 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009033 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009034 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009035 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009036 synchronized (sr.stats.getBatteryStats()) {
9037 sr.stats.stopLaunchedLocked();
9038 }
9039 sr.app = null;
9040 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009041 if (mStoppingServices.remove(sr)) {
9042 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
9043 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009044
9045 boolean hasClients = sr.bindings.size() > 0;
9046 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009047 Iterator<IntentBindRecord> bindings
9048 = sr.bindings.values().iterator();
9049 while (bindings.hasNext()) {
9050 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009051 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009052 + ": shouldUnbind=" + b.hasBound);
9053 b.binder = null;
9054 b.requested = b.received = b.hasBound = false;
9055 }
9056 }
9057
Dianne Hackborn070783f2010-12-29 16:46:28 -08009058 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
9059 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009060 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009061 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009062 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009063 sr.crashCount, sr.shortName, app.pid);
9064 bringDownServiceLocked(sr, true);
9065 } else if (!allowRestart) {
9066 bringDownServiceLocked(sr, true);
9067 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009068 boolean canceled = scheduleServiceRestartLocked(sr, true);
9069
9070 // Should the service remain running? Note that in the
9071 // extreme case of so many attempts to deliver a command
9072 // that it failed, that we also will stop it here.
9073 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
9074 if (sr.pendingStarts.size() == 0) {
9075 sr.startRequested = false;
9076 if (!hasClients) {
9077 // Whoops, no reason to restart!
9078 bringDownServiceLocked(sr, true);
9079 }
9080 }
9081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009082 }
9083 }
9084
9085 if (!allowRestart) {
9086 app.services.clear();
9087 }
9088 }
9089
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009090 // Make sure we have no more records on the stopping list.
9091 int i = mStoppingServices.size();
9092 while (i > 0) {
9093 i--;
9094 ServiceRecord sr = mStoppingServices.get(i);
9095 if (sr.app == app) {
9096 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009097 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009098 }
9099 }
9100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009101 app.executingServices.clear();
9102 }
9103
9104 private final void removeDyingProviderLocked(ProcessRecord proc,
9105 ContentProviderRecord cpr) {
9106 synchronized (cpr) {
9107 cpr.launchingApp = null;
9108 cpr.notifyAll();
9109 }
9110
9111 mProvidersByClass.remove(cpr.info.name);
9112 String names[] = cpr.info.authority.split(";");
9113 for (int j = 0; j < names.length; j++) {
9114 mProvidersByName.remove(names[j]);
9115 }
9116
9117 Iterator<ProcessRecord> cit = cpr.clients.iterator();
9118 while (cit.hasNext()) {
9119 ProcessRecord capp = cit.next();
9120 if (!capp.persistent && capp.thread != null
9121 && capp.pid != 0
9122 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009123 Slog.i(TAG, "Kill " + capp.processName
9124 + " (pid " + capp.pid + "): provider " + cpr.info.name
9125 + " in dying process " + proc.processName);
9126 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
9127 capp.processName, capp.setAdj, "dying provider " + proc.processName);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009128 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009129 }
9130 }
9131
9132 mLaunchingProviders.remove(cpr);
9133 }
9134
9135 /**
9136 * Main code for cleaning up a process when it has gone away. This is
9137 * called both as a result of the process dying, or directly when stopping
9138 * a process when running in single process mode.
9139 */
9140 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
9141 boolean restarting, int index) {
9142 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009143 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009144 }
9145
Dianne Hackborn36124872009-10-08 16:22:03 -07009146 mProcessesToGc.remove(app);
9147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009148 // Dismiss any open dialogs.
9149 if (app.crashDialog != null) {
9150 app.crashDialog.dismiss();
9151 app.crashDialog = null;
9152 }
9153 if (app.anrDialog != null) {
9154 app.anrDialog.dismiss();
9155 app.anrDialog = null;
9156 }
9157 if (app.waitDialog != null) {
9158 app.waitDialog.dismiss();
9159 app.waitDialog = null;
9160 }
9161
9162 app.crashing = false;
9163 app.notResponding = false;
9164
9165 app.resetPackageList();
9166 app.thread = null;
9167 app.forcingToForeground = null;
9168 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009169 app.foregroundActivities = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009170
9171 killServicesLocked(app, true);
9172
9173 boolean restart = false;
9174
9175 int NL = mLaunchingProviders.size();
9176
9177 // Remove published content providers.
9178 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009179 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009180 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009181 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182 cpr.provider = null;
9183 cpr.app = null;
9184
9185 // See if someone is waiting for this provider... in which
9186 // case we don't remove it, but just let it restart.
9187 int i = 0;
9188 if (!app.bad) {
9189 for (; i<NL; i++) {
9190 if (mLaunchingProviders.get(i) == cpr) {
9191 restart = true;
9192 break;
9193 }
9194 }
9195 } else {
9196 i = NL;
9197 }
9198
9199 if (i >= NL) {
9200 removeDyingProviderLocked(app, cpr);
9201 NL = mLaunchingProviders.size();
9202 }
9203 }
9204 app.pubProviders.clear();
9205 }
9206
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009207 // Take care of any launching providers waiting for this process.
9208 if (checkAppInLaunchingProvidersLocked(app, false)) {
9209 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009210 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009212 // Unregister from connected content providers.
9213 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009214 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009215 while (it.hasNext()) {
9216 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9217 cpr.clients.remove(app);
9218 }
9219 app.conProviders.clear();
9220 }
9221
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009222 // At this point there may be remaining entries in mLaunchingProviders
9223 // where we were the only one waiting, so they are no longer of use.
9224 // Look for these and clean up if found.
9225 // XXX Commented out for now. Trying to figure out a way to reproduce
9226 // the actual situation to identify what is actually going on.
9227 if (false) {
9228 for (int i=0; i<NL; i++) {
9229 ContentProviderRecord cpr = (ContentProviderRecord)
9230 mLaunchingProviders.get(i);
9231 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9232 synchronized (cpr) {
9233 cpr.launchingApp = null;
9234 cpr.notifyAll();
9235 }
9236 }
9237 }
9238 }
9239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 skipCurrentReceiverLocked(app);
9241
9242 // Unregister any receivers.
9243 if (app.receivers.size() > 0) {
9244 Iterator<ReceiverList> it = app.receivers.iterator();
9245 while (it.hasNext()) {
9246 removeReceiverLocked(it.next());
9247 }
9248 app.receivers.clear();
9249 }
9250
Christopher Tate181fafa2009-05-14 11:12:14 -07009251 // If the app is undergoing backup, tell the backup manager about it
9252 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009253 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009254 try {
9255 IBackupManager bm = IBackupManager.Stub.asInterface(
9256 ServiceManager.getService(Context.BACKUP_SERVICE));
9257 bm.agentDisconnected(app.info.packageName);
9258 } catch (RemoteException e) {
9259 // can't happen; backup manager is local
9260 }
9261 }
9262
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009263 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app).sendToTarget();
9264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009265 // If the caller is restarting this app, then leave it in its
9266 // current lists and let the caller take care of it.
9267 if (restarting) {
9268 return;
9269 }
9270
9271 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009272 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009273 "Removing non-persistent process during cleanup: " + app);
9274 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009275 if (mHeavyWeightProcess == app) {
9276 mHeavyWeightProcess = null;
9277 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009279 } else if (!app.removed) {
9280 // This app is persistent, so we need to keep its record around.
9281 // If it is not already on the pending app list, add it there
9282 // and start a new process for it.
9283 app.thread = null;
9284 app.forcingToForeground = null;
9285 app.foregroundServices = false;
9286 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9287 mPersistentStartingProcesses.add(app);
9288 restart = true;
9289 }
9290 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009291 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9292 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009293 mProcessesOnHold.remove(app);
9294
The Android Open Source Project4df24232009-03-05 14:34:35 -08009295 if (app == mHomeProcess) {
9296 mHomeProcess = null;
9297 }
9298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009299 if (restart) {
9300 // We have components that still need to be running in the
9301 // process, so re-launch it.
9302 mProcessNames.put(app.processName, app.info.uid, app);
9303 startProcessLocked(app, "restart", app.processName);
9304 } else if (app.pid > 0 && app.pid != MY_PID) {
9305 // Goodbye!
9306 synchronized (mPidsSelfLocked) {
9307 mPidsSelfLocked.remove(app.pid);
9308 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9309 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009310 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009311 }
9312 }
9313
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009314 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9315 // Look through the content providers we are waiting to have launched,
9316 // and if any run in this process then either schedule a restart of
9317 // the process or kill the client waiting for it if this process has
9318 // gone bad.
9319 int NL = mLaunchingProviders.size();
9320 boolean restart = false;
9321 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009322 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009323 if (cpr.launchingApp == app) {
9324 if (!alwaysBad && !app.bad) {
9325 restart = true;
9326 } else {
9327 removeDyingProviderLocked(app, cpr);
9328 NL = mLaunchingProviders.size();
9329 }
9330 }
9331 }
9332 return restart;
9333 }
9334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009335 // =========================================================
9336 // SERVICES
9337 // =========================================================
9338
9339 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9340 ActivityManager.RunningServiceInfo info =
9341 new ActivityManager.RunningServiceInfo();
9342 info.service = r.name;
9343 if (r.app != null) {
9344 info.pid = r.app.pid;
9345 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009346 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009347 info.process = r.processName;
9348 info.foreground = r.isForeground;
9349 info.activeSince = r.createTime;
9350 info.started = r.startRequested;
9351 info.clientCount = r.connections.size();
9352 info.crashCount = r.crashCount;
9353 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009354 if (r.isForeground) {
9355 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9356 }
9357 if (r.startRequested) {
9358 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9359 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009360 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009361 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9362 }
9363 if (r.app != null && r.app.persistent) {
9364 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9365 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009366
9367 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9368 for (int i=0; i<connl.size(); i++) {
9369 ConnectionRecord conn = connl.get(i);
9370 if (conn.clientLabel != 0) {
9371 info.clientPackage = conn.binding.client.info.packageName;
9372 info.clientLabel = conn.clientLabel;
9373 return info;
9374 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009375 }
9376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009377 return info;
9378 }
9379
9380 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9381 int flags) {
9382 synchronized (this) {
9383 ArrayList<ActivityManager.RunningServiceInfo> res
9384 = new ArrayList<ActivityManager.RunningServiceInfo>();
9385
9386 if (mServices.size() > 0) {
9387 Iterator<ServiceRecord> it = mServices.values().iterator();
9388 while (it.hasNext() && res.size() < maxNum) {
9389 res.add(makeRunningServiceInfoLocked(it.next()));
9390 }
9391 }
9392
9393 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9394 ServiceRecord r = mRestartingServices.get(i);
9395 ActivityManager.RunningServiceInfo info =
9396 makeRunningServiceInfoLocked(r);
9397 info.restarting = r.nextRestartTime;
9398 res.add(info);
9399 }
9400
9401 return res;
9402 }
9403 }
9404
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009405 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9406 synchronized (this) {
9407 ServiceRecord r = mServices.get(name);
9408 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009409 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9410 for (int i=0; i<conn.size(); i++) {
9411 if (conn.get(i).clientIntent != null) {
9412 return conn.get(i).clientIntent;
9413 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009414 }
9415 }
9416 }
9417 }
9418 return null;
9419 }
9420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009421 private final ServiceRecord findServiceLocked(ComponentName name,
9422 IBinder token) {
9423 ServiceRecord r = mServices.get(name);
9424 return r == token ? r : null;
9425 }
9426
9427 private final class ServiceLookupResult {
9428 final ServiceRecord record;
9429 final String permission;
9430
9431 ServiceLookupResult(ServiceRecord _record, String _permission) {
9432 record = _record;
9433 permission = _permission;
9434 }
9435 };
9436
9437 private ServiceLookupResult findServiceLocked(Intent service,
9438 String resolvedType) {
9439 ServiceRecord r = null;
9440 if (service.getComponent() != null) {
9441 r = mServices.get(service.getComponent());
9442 }
9443 if (r == null) {
9444 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9445 r = mServicesByIntent.get(filter);
9446 }
9447
9448 if (r == null) {
9449 try {
9450 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009451 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 service, resolvedType, 0);
9453 ServiceInfo sInfo =
9454 rInfo != null ? rInfo.serviceInfo : null;
9455 if (sInfo == null) {
9456 return null;
9457 }
9458
9459 ComponentName name = new ComponentName(
9460 sInfo.applicationInfo.packageName, sInfo.name);
9461 r = mServices.get(name);
9462 } catch (RemoteException ex) {
9463 // pm is in same process, this will never happen.
9464 }
9465 }
9466 if (r != null) {
9467 int callingPid = Binder.getCallingPid();
9468 int callingUid = Binder.getCallingUid();
9469 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009470 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009472 if (!r.exported) {
9473 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9474 + " from pid=" + callingPid
9475 + ", uid=" + callingUid
9476 + " that is not exported from uid " + r.appInfo.uid);
9477 return new ServiceLookupResult(null, "not exported from uid "
9478 + r.appInfo.uid);
9479 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009480 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009481 + " from pid=" + callingPid
9482 + ", uid=" + callingUid
9483 + " requires " + r.permission);
9484 return new ServiceLookupResult(null, r.permission);
9485 }
9486 return new ServiceLookupResult(r, null);
9487 }
9488 return null;
9489 }
9490
9491 private class ServiceRestarter implements Runnable {
9492 private ServiceRecord mService;
9493
9494 void setService(ServiceRecord service) {
9495 mService = service;
9496 }
9497
9498 public void run() {
9499 synchronized(ActivityManagerService.this) {
9500 performServiceRestartLocked(mService);
9501 }
9502 }
9503 }
9504
9505 private ServiceLookupResult retrieveServiceLocked(Intent service,
9506 String resolvedType, int callingPid, int callingUid) {
9507 ServiceRecord r = null;
9508 if (service.getComponent() != null) {
9509 r = mServices.get(service.getComponent());
9510 }
9511 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9512 r = mServicesByIntent.get(filter);
9513 if (r == null) {
9514 try {
9515 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009516 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009517 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009518 ServiceInfo sInfo =
9519 rInfo != null ? rInfo.serviceInfo : null;
9520 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009521 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009522 ": not found");
9523 return null;
9524 }
9525
9526 ComponentName name = new ComponentName(
9527 sInfo.applicationInfo.packageName, sInfo.name);
9528 r = mServices.get(name);
9529 if (r == null) {
9530 filter = new Intent.FilterComparison(service.cloneFilter());
9531 ServiceRestarter res = new ServiceRestarter();
9532 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9533 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9534 synchronized (stats) {
9535 ss = stats.getServiceStatsLocked(
9536 sInfo.applicationInfo.uid, sInfo.packageName,
9537 sInfo.name);
9538 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009539 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009540 res.setService(r);
9541 mServices.put(name, r);
9542 mServicesByIntent.put(filter, r);
9543
9544 // Make sure this component isn't in the pending list.
9545 int N = mPendingServices.size();
9546 for (int i=0; i<N; i++) {
9547 ServiceRecord pr = mPendingServices.get(i);
9548 if (pr.name.equals(name)) {
9549 mPendingServices.remove(i);
9550 i--;
9551 N--;
9552 }
9553 }
9554 }
9555 } catch (RemoteException ex) {
9556 // pm is in same process, this will never happen.
9557 }
9558 }
9559 if (r != null) {
9560 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009561 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009562 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009563 if (!r.exported) {
9564 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9565 + " from pid=" + callingPid
9566 + ", uid=" + callingUid
9567 + " that is not exported from uid " + r.appInfo.uid);
9568 return new ServiceLookupResult(null, "not exported from uid "
9569 + r.appInfo.uid);
9570 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009571 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009572 + " from pid=" + callingPid
9573 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009574 + " requires " + r.permission);
9575 return new ServiceLookupResult(null, r.permission);
9576 }
9577 return new ServiceLookupResult(r, null);
9578 }
9579 return null;
9580 }
9581
Dianne Hackborn287952c2010-09-22 22:34:31 -07009582 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9583 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9584 + why + " of " + r + " in app " + r.app);
9585 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9586 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009587 long now = SystemClock.uptimeMillis();
9588 if (r.executeNesting == 0 && r.app != null) {
9589 if (r.app.executingServices.size() == 0) {
9590 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9591 msg.obj = r.app;
9592 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9593 }
9594 r.app.executingServices.add(r);
9595 }
9596 r.executeNesting++;
9597 r.executingStart = now;
9598 }
9599
9600 private final void sendServiceArgsLocked(ServiceRecord r,
9601 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009602 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009603 if (N == 0) {
9604 return;
9605 }
9606
Dianne Hackborn39792d22010-08-19 18:01:52 -07009607 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009608 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009609 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009610 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9611 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009612 if (si.intent == null && N > 1) {
9613 // If somehow we got a dummy null intent in the middle,
9614 // then skip it. DO NOT skip a null intent when it is
9615 // the only one in the list -- this is to support the
9616 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009617 continue;
9618 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009619 si.deliveredTime = SystemClock.uptimeMillis();
9620 r.deliveredStarts.add(si);
9621 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009622 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009623 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009624 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009625 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009626 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009627 if (!oomAdjusted) {
9628 oomAdjusted = true;
9629 updateOomAdjLocked(r.app);
9630 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009631 int flags = 0;
9632 if (si.deliveryCount > 0) {
9633 flags |= Service.START_FLAG_RETRY;
9634 }
9635 if (si.doneExecutingCount > 0) {
9636 flags |= Service.START_FLAG_REDELIVERY;
9637 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009638 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009639 } catch (RemoteException e) {
9640 // Remote process gone... we'll let the normal cleanup take
9641 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009642 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009643 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009644 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009645 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009646 break;
9647 }
9648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009649 }
9650
9651 private final boolean requestServiceBindingLocked(ServiceRecord r,
9652 IntentBindRecord i, boolean rebind) {
9653 if (r.app == null || r.app.thread == null) {
9654 // If service is not currently running, can't yet bind.
9655 return false;
9656 }
9657 if ((!i.requested || rebind) && i.apps.size() > 0) {
9658 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009659 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009660 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9661 if (!rebind) {
9662 i.requested = true;
9663 }
9664 i.hasBound = true;
9665 i.doRebind = false;
9666 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009667 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009668 return false;
9669 }
9670 }
9671 return true;
9672 }
9673
9674 private final void requestServiceBindingsLocked(ServiceRecord r) {
9675 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9676 while (bindings.hasNext()) {
9677 IntentBindRecord i = bindings.next();
9678 if (!requestServiceBindingLocked(r, i, false)) {
9679 break;
9680 }
9681 }
9682 }
9683
9684 private final void realStartServiceLocked(ServiceRecord r,
9685 ProcessRecord app) throws RemoteException {
9686 if (app.thread == null) {
9687 throw new RemoteException();
9688 }
9689
9690 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009691 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692
9693 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009694 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009695 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009696
9697 boolean created = false;
9698 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009699 mStringBuilder.setLength(0);
9700 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009701 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009703 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009704 synchronized (r.stats.getBatteryStats()) {
9705 r.stats.startLaunchedLocked();
9706 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009707 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04009708 app.thread.scheduleCreateService(r, r.serviceInfo,
9709 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009710 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009711 created = true;
9712 } finally {
9713 if (!created) {
9714 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009715 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009716 }
9717 }
9718
9719 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009720
9721 // If the service is in the started state, and there are no
9722 // pending arguments, then fake up one so its onStartCommand() will
9723 // be called.
9724 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009725 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
9726 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009727 }
9728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009729 sendServiceArgsLocked(r, true);
9730 }
9731
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009732 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9733 boolean allowCancel) {
9734 boolean canceled = false;
9735
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009736 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009737 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009738 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009739
Dianne Hackborn070783f2010-12-29 16:46:28 -08009740 if ((r.serviceInfo.applicationInfo.flags
9741 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9742 minDuration /= 4;
9743 }
9744
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009745 // Any delivered but not yet finished starts should be put back
9746 // on the pending list.
9747 final int N = r.deliveredStarts.size();
9748 if (N > 0) {
9749 for (int i=N-1; i>=0; i--) {
9750 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009751 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009752 if (si.intent == null) {
9753 // We'll generate this again if needed.
9754 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9755 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9756 r.pendingStarts.add(0, si);
9757 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9758 dur *= 2;
9759 if (minDuration < dur) minDuration = dur;
9760 if (resetTime < dur) resetTime = dur;
9761 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009762 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009763 + r.name);
9764 canceled = true;
9765 }
9766 }
9767 r.deliveredStarts.clear();
9768 }
9769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009770 r.totalRestartCount++;
9771 if (r.restartDelay == 0) {
9772 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009773 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009774 } else {
9775 // If it has been a "reasonably long time" since the service
9776 // was started, then reset our restart duration back to
9777 // the beginning, so we don't infinitely increase the duration
9778 // on a service that just occasionally gets killed (which is
9779 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009780 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009781 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009782 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009783 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009784 if ((r.serviceInfo.applicationInfo.flags
9785 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9786 // Services in peristent processes will restart much more
9787 // quickly, since they are pretty important. (Think SystemUI).
9788 r.restartDelay += minDuration/2;
9789 } else {
9790 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9791 if (r.restartDelay < minDuration) {
9792 r.restartDelay = minDuration;
9793 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009795 }
9796 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009797
9798 r.nextRestartTime = now + r.restartDelay;
9799
9800 // Make sure that we don't end up restarting a bunch of services
9801 // all at the same time.
9802 boolean repeat;
9803 do {
9804 repeat = false;
9805 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9806 ServiceRecord r2 = mRestartingServices.get(i);
9807 if (r2 != r && r.nextRestartTime
9808 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9809 && r.nextRestartTime
9810 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9811 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9812 r.restartDelay = r.nextRestartTime - now;
9813 repeat = true;
9814 break;
9815 }
9816 }
9817 } while (repeat);
9818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009819 if (!mRestartingServices.contains(r)) {
9820 mRestartingServices.add(r);
9821 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009822
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009823 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009825 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009826 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009827 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009828 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009829 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009830 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009831 r.shortName, r.restartDelay);
9832
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009833 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009834 }
9835
9836 final void performServiceRestartLocked(ServiceRecord r) {
9837 if (!mRestartingServices.contains(r)) {
9838 return;
9839 }
9840 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9841 }
9842
9843 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9844 if (r.restartDelay == 0) {
9845 return false;
9846 }
9847 r.resetRestartCounter();
9848 mRestartingServices.remove(r);
9849 mHandler.removeCallbacks(r.restarter);
9850 return true;
9851 }
9852
9853 private final boolean bringUpServiceLocked(ServiceRecord r,
9854 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009855 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009856 //r.dump(" ");
9857
Dianne Hackborn36124872009-10-08 16:22:03 -07009858 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009859 sendServiceArgsLocked(r, false);
9860 return true;
9861 }
9862
9863 if (!whileRestarting && r.restartDelay > 0) {
9864 // If waiting for a restart, then do nothing.
9865 return true;
9866 }
9867
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009868 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009869
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009870 // We are now bringing the service up, so no longer in the
9871 // restarting state.
9872 mRestartingServices.remove(r);
9873
Dianne Hackborne7f97212011-02-24 14:40:20 -08009874 // Service is now being launched, its package can't be stopped.
9875 try {
9876 AppGlobals.getPackageManager().setPackageStoppedState(
9877 r.packageName, false);
9878 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009879 } catch (IllegalArgumentException e) {
9880 Slog.w(TAG, "Failed trying to unstop package "
9881 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009882 }
9883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009884 final String appName = r.processName;
9885 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9886 if (app != null && app.thread != null) {
9887 try {
9888 realStartServiceLocked(r, app);
9889 return true;
9890 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009891 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 }
9893
9894 // If a dead object exception was thrown -- fall through to
9895 // restart the application.
9896 }
9897
Dianne Hackborn36124872009-10-08 16:22:03 -07009898 // Not running -- get it started, and enqueue this service record
9899 // to be executed when the app comes up.
9900 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9901 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009902 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009903 + r.appInfo.packageName + "/"
9904 + r.appInfo.uid + " for service "
9905 + r.intent.getIntent() + ": process is bad");
9906 bringDownServiceLocked(r, true);
9907 return false;
9908 }
9909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009910 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009911 mPendingServices.add(r);
9912 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009914 return true;
9915 }
9916
9917 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009918 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009919 //r.dump(" ");
9920
9921 // Does it still need to run?
9922 if (!force && r.startRequested) {
9923 return;
9924 }
9925 if (r.connections.size() > 0) {
9926 if (!force) {
9927 // XXX should probably keep a count of the number of auto-create
9928 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009929 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009930 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009931 ArrayList<ConnectionRecord> cr = it.next();
9932 for (int i=0; i<cr.size(); i++) {
9933 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9934 return;
9935 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009936 }
9937 }
9938 }
9939
9940 // Report to all of the connections that the service is no longer
9941 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009942 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009944 ArrayList<ConnectionRecord> c = it.next();
9945 for (int i=0; i<c.size(); i++) {
9946 try {
9947 c.get(i).conn.connected(r.name, null);
9948 } catch (Exception e) {
9949 Slog.w(TAG, "Failure disconnecting service " + r.name +
9950 " to connection " + c.get(i).conn.asBinder() +
9951 " (in " + c.get(i).binding.client.processName + ")", e);
9952 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009953 }
9954 }
9955 }
9956
9957 // Tell the service that it has been unbound.
9958 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9959 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9960 while (it.hasNext()) {
9961 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009962 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009963 + ": hasBound=" + ibr.hasBound);
9964 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9965 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009966 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009967 updateOomAdjLocked(r.app);
9968 ibr.hasBound = false;
9969 r.app.thread.scheduleUnbindService(r,
9970 ibr.intent.getIntent());
9971 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009972 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009973 + r.shortName, e);
9974 serviceDoneExecutingLocked(r, true);
9975 }
9976 }
9977 }
9978 }
9979
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009980 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009981 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009982 System.identityHashCode(r), r.shortName,
9983 (r.app != null) ? r.app.pid : -1);
9984
9985 mServices.remove(r.name);
9986 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009987 r.totalRestartCount = 0;
9988 unscheduleServiceRestartLocked(r);
9989
9990 // Also make sure it is not on the pending list.
9991 int N = mPendingServices.size();
9992 for (int i=0; i<N; i++) {
9993 if (mPendingServices.get(i) == r) {
9994 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009995 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009996 i--;
9997 N--;
9998 }
9999 }
10000
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010001 r.cancelNotification();
10002 r.isForeground = false;
10003 r.foregroundId = 0;
10004 r.foregroundNoti = null;
10005
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010006 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070010007 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010008 r.pendingStarts.clear();
10009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010010 if (r.app != null) {
10011 synchronized (r.stats.getBatteryStats()) {
10012 r.stats.stopLaunchedLocked();
10013 }
10014 r.app.services.remove(r);
10015 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010016 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010017 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010018 mStoppingServices.add(r);
10019 updateOomAdjLocked(r.app);
10020 r.app.thread.scheduleStopService(r);
10021 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010022 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010023 + r.shortName, e);
10024 serviceDoneExecutingLocked(r, true);
10025 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010026 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010027 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010028 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010029 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010030 }
10031 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010032 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010033 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010034 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080010035
10036 if (r.bindings.size() > 0) {
10037 r.bindings.clear();
10038 }
10039
10040 if (r.restarter instanceof ServiceRestarter) {
10041 ((ServiceRestarter)r.restarter).setService(null);
10042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010043 }
10044
10045 ComponentName startServiceLocked(IApplicationThread caller,
10046 Intent service, String resolvedType,
10047 int callingPid, int callingUid) {
10048 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010049 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010050 + " type=" + resolvedType + " args=" + service.getExtras());
10051
10052 if (caller != null) {
10053 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10054 if (callerApp == null) {
10055 throw new SecurityException(
10056 "Unable to find app for caller " + caller
10057 + " (pid=" + Binder.getCallingPid()
10058 + ") when starting service " + service);
10059 }
10060 }
10061
10062 ServiceLookupResult res =
10063 retrieveServiceLocked(service, resolvedType,
10064 callingPid, callingUid);
10065 if (res == null) {
10066 return null;
10067 }
10068 if (res.record == null) {
10069 return new ComponentName("!", res.permission != null
10070 ? res.permission : "private to package");
10071 }
10072 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070010073 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
10074 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010076 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010077 }
10078 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010079 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010080 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070010081 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010082 r.lastActivity = SystemClock.uptimeMillis();
10083 synchronized (r.stats.getBatteryStats()) {
10084 r.stats.startRunningLocked();
10085 }
10086 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
10087 return new ComponentName("!", "Service process is bad");
10088 }
10089 return r.name;
10090 }
10091 }
10092
10093 public ComponentName startService(IApplicationThread caller, Intent service,
10094 String resolvedType) {
10095 // Refuse possible leaked file descriptors
10096 if (service != null && service.hasFileDescriptors() == true) {
10097 throw new IllegalArgumentException("File descriptors passed in Intent");
10098 }
10099
10100 synchronized(this) {
10101 final int callingPid = Binder.getCallingPid();
10102 final int callingUid = Binder.getCallingUid();
10103 final long origId = Binder.clearCallingIdentity();
10104 ComponentName res = startServiceLocked(caller, service,
10105 resolvedType, callingPid, callingUid);
10106 Binder.restoreCallingIdentity(origId);
10107 return res;
10108 }
10109 }
10110
10111 ComponentName startServiceInPackage(int uid,
10112 Intent service, String resolvedType) {
10113 synchronized(this) {
10114 final long origId = Binder.clearCallingIdentity();
10115 ComponentName res = startServiceLocked(null, service,
10116 resolvedType, -1, uid);
10117 Binder.restoreCallingIdentity(origId);
10118 return res;
10119 }
10120 }
10121
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010122 private void stopServiceLocked(ServiceRecord service) {
10123 synchronized (service.stats.getBatteryStats()) {
10124 service.stats.stopRunningLocked();
10125 }
10126 service.startRequested = false;
10127 service.callStart = false;
10128 bringDownServiceLocked(service, false);
10129 }
10130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010131 public int stopService(IApplicationThread caller, Intent service,
10132 String resolvedType) {
10133 // Refuse possible leaked file descriptors
10134 if (service != null && service.hasFileDescriptors() == true) {
10135 throw new IllegalArgumentException("File descriptors passed in Intent");
10136 }
10137
10138 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010139 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 + " type=" + resolvedType);
10141
10142 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10143 if (caller != null && callerApp == null) {
10144 throw new SecurityException(
10145 "Unable to find app for caller " + caller
10146 + " (pid=" + Binder.getCallingPid()
10147 + ") when stopping service " + service);
10148 }
10149
10150 // If this service is active, make sure it is stopped.
10151 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10152 if (r != null) {
10153 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010154 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010155 try {
10156 stopServiceLocked(r.record);
10157 } finally {
10158 Binder.restoreCallingIdentity(origId);
10159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010160 return 1;
10161 }
10162 return -1;
10163 }
10164 }
10165
10166 return 0;
10167 }
10168
10169 public IBinder peekService(Intent service, String resolvedType) {
10170 // Refuse possible leaked file descriptors
10171 if (service != null && service.hasFileDescriptors() == true) {
10172 throw new IllegalArgumentException("File descriptors passed in Intent");
10173 }
10174
10175 IBinder ret = null;
10176
10177 synchronized(this) {
10178 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10179
10180 if (r != null) {
10181 // r.record is null if findServiceLocked() failed the caller permission check
10182 if (r.record == null) {
10183 throw new SecurityException(
10184 "Permission Denial: Accessing service " + r.record.name
10185 + " from pid=" + Binder.getCallingPid()
10186 + ", uid=" + Binder.getCallingUid()
10187 + " requires " + r.permission);
10188 }
10189 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10190 if (ib != null) {
10191 ret = ib.binder;
10192 }
10193 }
10194 }
10195
10196 return ret;
10197 }
10198
10199 public boolean stopServiceToken(ComponentName className, IBinder token,
10200 int startId) {
10201 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010202 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010203 + " " + token + " startId=" + startId);
10204 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010205 if (r != null) {
10206 if (startId >= 0) {
10207 // Asked to only stop if done with all work. Note that
10208 // to avoid leaks, we will take this as dropping all
10209 // start items up to and including this one.
10210 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10211 if (si != null) {
10212 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010213 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10214 cur.removeUriPermissionsLocked();
10215 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010216 break;
10217 }
10218 }
10219 }
10220
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010221 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010222 return false;
10223 }
10224
10225 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010226 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010227 + " is last, but have " + r.deliveredStarts.size()
10228 + " remaining args");
10229 }
10230 }
10231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010232 synchronized (r.stats.getBatteryStats()) {
10233 r.stats.stopRunningLocked();
10234 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010235 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236 }
10237 final long origId = Binder.clearCallingIdentity();
10238 bringDownServiceLocked(r, false);
10239 Binder.restoreCallingIdentity(origId);
10240 return true;
10241 }
10242 }
10243 return false;
10244 }
10245
10246 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010247 int id, Notification notification, boolean removeNotification) {
10248 final long origId = Binder.clearCallingIdentity();
10249 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010250 synchronized(this) {
10251 ServiceRecord r = findServiceLocked(className, token);
10252 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010253 if (id != 0) {
10254 if (notification == null) {
10255 throw new IllegalArgumentException("null notification");
10256 }
10257 if (r.foregroundId != id) {
10258 r.cancelNotification();
10259 r.foregroundId = id;
10260 }
10261 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10262 r.foregroundNoti = notification;
10263 r.isForeground = true;
10264 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010265 if (r.app != null) {
10266 updateServiceForegroundLocked(r.app, true);
10267 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010268 } else {
10269 if (r.isForeground) {
10270 r.isForeground = false;
10271 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010272 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010273 updateServiceForegroundLocked(r.app, true);
10274 }
10275 }
10276 if (removeNotification) {
10277 r.cancelNotification();
10278 r.foregroundId = 0;
10279 r.foregroundNoti = null;
10280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010281 }
10282 }
10283 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010284 } finally {
10285 Binder.restoreCallingIdentity(origId);
10286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010287 }
10288
10289 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10290 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010291 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292 if (sr.isForeground) {
10293 anyForeground = true;
10294 break;
10295 }
10296 }
10297 if (anyForeground != proc.foregroundServices) {
10298 proc.foregroundServices = anyForeground;
10299 if (oomAdj) {
10300 updateOomAdjLocked();
10301 }
10302 }
10303 }
10304
10305 public int bindService(IApplicationThread caller, IBinder token,
10306 Intent service, String resolvedType,
10307 IServiceConnection connection, int flags) {
10308 // Refuse possible leaked file descriptors
10309 if (service != null && service.hasFileDescriptors() == true) {
10310 throw new IllegalArgumentException("File descriptors passed in Intent");
10311 }
10312
10313 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010314 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 + " type=" + resolvedType + " conn=" + connection.asBinder()
10316 + " flags=0x" + Integer.toHexString(flags));
10317 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10318 if (callerApp == null) {
10319 throw new SecurityException(
10320 "Unable to find app for caller " + caller
10321 + " (pid=" + Binder.getCallingPid()
10322 + ") when binding service " + service);
10323 }
10324
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010325 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010326 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010327 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010328 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010329 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010330 return 0;
10331 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010332 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010333 }
10334
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010335 int clientLabel = 0;
10336 PendingIntent clientIntent = null;
10337
10338 if (callerApp.info.uid == Process.SYSTEM_UID) {
10339 // Hacky kind of thing -- allow system stuff to tell us
10340 // what they are, so we can report this elsewhere for
10341 // others to know why certain services are running.
10342 try {
10343 clientIntent = (PendingIntent)service.getParcelableExtra(
10344 Intent.EXTRA_CLIENT_INTENT);
10345 } catch (RuntimeException e) {
10346 }
10347 if (clientIntent != null) {
10348 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10349 if (clientLabel != 0) {
10350 // There are no useful extras in the intent, trash them.
10351 // System code calling with this stuff just needs to know
10352 // this will happen.
10353 service = service.cloneFilter();
10354 }
10355 }
10356 }
10357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010358 ServiceLookupResult res =
10359 retrieveServiceLocked(service, resolvedType,
10360 Binder.getCallingPid(), Binder.getCallingUid());
10361 if (res == null) {
10362 return 0;
10363 }
10364 if (res.record == null) {
10365 return -1;
10366 }
10367 ServiceRecord s = res.record;
10368
10369 final long origId = Binder.clearCallingIdentity();
10370
10371 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010372 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010373 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010374 }
10375
10376 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10377 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010378 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010379
10380 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010381 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10382 if (clist == null) {
10383 clist = new ArrayList<ConnectionRecord>();
10384 s.connections.put(binder, clist);
10385 }
10386 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010387 b.connections.add(c);
10388 if (activity != null) {
10389 if (activity.connections == null) {
10390 activity.connections = new HashSet<ConnectionRecord>();
10391 }
10392 activity.connections.add(c);
10393 }
10394 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010395 clist = mServiceConnections.get(binder);
10396 if (clist == null) {
10397 clist = new ArrayList<ConnectionRecord>();
10398 mServiceConnections.put(binder, clist);
10399 }
10400 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010401
10402 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10403 s.lastActivity = SystemClock.uptimeMillis();
10404 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10405 return 0;
10406 }
10407 }
10408
10409 if (s.app != null) {
10410 // This could have made the service more important.
10411 updateOomAdjLocked(s.app);
10412 }
10413
Joe Onorato8a9b2202010-02-26 18:56:32 -080010414 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010415 + ": received=" + b.intent.received
10416 + " apps=" + b.intent.apps.size()
10417 + " doRebind=" + b.intent.doRebind);
10418
10419 if (s.app != null && b.intent.received) {
10420 // Service is already running, so we can immediately
10421 // publish the connection.
10422 try {
10423 c.conn.connected(s.name, b.intent.binder);
10424 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010425 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010426 + " to connection " + c.conn.asBinder()
10427 + " (in " + c.binding.client.processName + ")", e);
10428 }
10429
10430 // If this is the first app connected back to this binding,
10431 // and the service had previously asked to be told when
10432 // rebound, then do so.
10433 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10434 requestServiceBindingLocked(s, b.intent, true);
10435 }
10436 } else if (!b.intent.requested) {
10437 requestServiceBindingLocked(s, b.intent, false);
10438 }
10439
10440 Binder.restoreCallingIdentity(origId);
10441 }
10442
10443 return 1;
10444 }
10445
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010446 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010447 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010448 IBinder binder = c.conn.asBinder();
10449 AppBindRecord b = c.binding;
10450 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010451 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10452 if (clist != null) {
10453 clist.remove(c);
10454 if (clist.size() == 0) {
10455 s.connections.remove(binder);
10456 }
10457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010458 b.connections.remove(c);
10459 if (c.activity != null && c.activity != skipAct) {
10460 if (c.activity.connections != null) {
10461 c.activity.connections.remove(c);
10462 }
10463 }
10464 if (b.client != skipApp) {
10465 b.client.connections.remove(c);
10466 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010467 clist = mServiceConnections.get(binder);
10468 if (clist != null) {
10469 clist.remove(c);
10470 if (clist.size() == 0) {
10471 mServiceConnections.remove(binder);
10472 }
10473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010474
10475 if (b.connections.size() == 0) {
10476 b.intent.apps.remove(b.client);
10477 }
10478
Joe Onorato8a9b2202010-02-26 18:56:32 -080010479 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010480 + ": shouldUnbind=" + b.intent.hasBound);
10481 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10482 && b.intent.hasBound) {
10483 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010484 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010485 updateOomAdjLocked(s.app);
10486 b.intent.hasBound = false;
10487 // Assume the client doesn't want to know about a rebind;
10488 // we will deal with that later if it asks for one.
10489 b.intent.doRebind = false;
10490 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10491 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010492 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010493 serviceDoneExecutingLocked(s, true);
10494 }
10495 }
10496
10497 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10498 bringDownServiceLocked(s, false);
10499 }
10500 }
10501
10502 public boolean unbindService(IServiceConnection connection) {
10503 synchronized (this) {
10504 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010505 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010506 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10507 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010508 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010509 + connection.asBinder());
10510 return false;
10511 }
10512
10513 final long origId = Binder.clearCallingIdentity();
10514
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010515 while (clist.size() > 0) {
10516 ConnectionRecord r = clist.get(0);
10517 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010518
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010519 if (r.binding.service.app != null) {
10520 // This could have made the service less important.
10521 updateOomAdjLocked(r.binding.service.app);
10522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010523 }
10524
10525 Binder.restoreCallingIdentity(origId);
10526 }
10527
10528 return true;
10529 }
10530
10531 public void publishService(IBinder token, Intent intent, IBinder service) {
10532 // Refuse possible leaked file descriptors
10533 if (intent != null && intent.hasFileDescriptors() == true) {
10534 throw new IllegalArgumentException("File descriptors passed in Intent");
10535 }
10536
10537 synchronized(this) {
10538 if (!(token instanceof ServiceRecord)) {
10539 throw new IllegalArgumentException("Invalid service token");
10540 }
10541 ServiceRecord r = (ServiceRecord)token;
10542
10543 final long origId = Binder.clearCallingIdentity();
10544
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010545 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 + " " + intent + ": " + service);
10547 if (r != null) {
10548 Intent.FilterComparison filter
10549 = new Intent.FilterComparison(intent);
10550 IntentBindRecord b = r.bindings.get(filter);
10551 if (b != null && !b.received) {
10552 b.binder = service;
10553 b.requested = true;
10554 b.received = true;
10555 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010556 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010557 = r.connections.values().iterator();
10558 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010559 ArrayList<ConnectionRecord> clist = it.next();
10560 for (int i=0; i<clist.size(); i++) {
10561 ConnectionRecord c = clist.get(i);
10562 if (!filter.equals(c.binding.intent.intent)) {
10563 if (DEBUG_SERVICE) Slog.v(
10564 TAG, "Not publishing to: " + c);
10565 if (DEBUG_SERVICE) Slog.v(
10566 TAG, "Bound intent: " + c.binding.intent.intent);
10567 if (DEBUG_SERVICE) Slog.v(
10568 TAG, "Published intent: " + intent);
10569 continue;
10570 }
10571 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10572 try {
10573 c.conn.connected(r.name, service);
10574 } catch (Exception e) {
10575 Slog.w(TAG, "Failure sending service " + r.name +
10576 " to connection " + c.conn.asBinder() +
10577 " (in " + c.binding.client.processName + ")", e);
10578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010579 }
10580 }
10581 }
10582 }
10583
10584 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10585
10586 Binder.restoreCallingIdentity(origId);
10587 }
10588 }
10589 }
10590
10591 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10592 // Refuse possible leaked file descriptors
10593 if (intent != null && intent.hasFileDescriptors() == true) {
10594 throw new IllegalArgumentException("File descriptors passed in Intent");
10595 }
10596
10597 synchronized(this) {
10598 if (!(token instanceof ServiceRecord)) {
10599 throw new IllegalArgumentException("Invalid service token");
10600 }
10601 ServiceRecord r = (ServiceRecord)token;
10602
10603 final long origId = Binder.clearCallingIdentity();
10604
10605 if (r != null) {
10606 Intent.FilterComparison filter
10607 = new Intent.FilterComparison(intent);
10608 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010609 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010610 + " at " + b + ": apps="
10611 + (b != null ? b.apps.size() : 0));
10612 if (b != null) {
10613 if (b.apps.size() > 0) {
10614 // Applications have already bound since the last
10615 // unbind, so just rebind right here.
10616 requestServiceBindingLocked(r, b, true);
10617 } else {
10618 // Note to tell the service the next time there is
10619 // a new client.
10620 b.doRebind = true;
10621 }
10622 }
10623
10624 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10625
10626 Binder.restoreCallingIdentity(origId);
10627 }
10628 }
10629 }
10630
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010631 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010632 synchronized(this) {
10633 if (!(token instanceof ServiceRecord)) {
10634 throw new IllegalArgumentException("Invalid service token");
10635 }
10636 ServiceRecord r = (ServiceRecord)token;
10637 boolean inStopping = mStoppingServices.contains(token);
10638 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010639 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010640 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010641 + " with incorrect token: given " + token
10642 + ", expected " + r);
10643 return;
10644 }
10645
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010646 if (type == 1) {
10647 // This is a call from a service start... take care of
10648 // book-keeping.
10649 r.callStart = true;
10650 switch (res) {
10651 case Service.START_STICKY_COMPATIBILITY:
10652 case Service.START_STICKY: {
10653 // We are done with the associated start arguments.
10654 r.findDeliveredStart(startId, true);
10655 // Don't stop if killed.
10656 r.stopIfKilled = false;
10657 break;
10658 }
10659 case Service.START_NOT_STICKY: {
10660 // We are done with the associated start arguments.
10661 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010662 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010663 // There is no more work, and this service
10664 // doesn't want to hang around if killed.
10665 r.stopIfKilled = true;
10666 }
10667 break;
10668 }
10669 case Service.START_REDELIVER_INTENT: {
10670 // We'll keep this item until they explicitly
10671 // call stop for it, but keep track of the fact
10672 // that it was delivered.
10673 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10674 if (si != null) {
10675 si.deliveryCount = 0;
10676 si.doneExecutingCount++;
10677 // Don't stop if killed.
10678 r.stopIfKilled = true;
10679 }
10680 break;
10681 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010682 case Service.START_TASK_REMOVED_COMPLETE: {
10683 // Special processing for onTaskRemoved(). Don't
10684 // impact normal onStartCommand() processing.
10685 r.findDeliveredStart(startId, true);
10686 break;
10687 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010688 default:
10689 throw new IllegalArgumentException(
10690 "Unknown service start result: " + res);
10691 }
10692 if (res == Service.START_STICKY_COMPATIBILITY) {
10693 r.callStart = false;
10694 }
10695 }
10696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010697 final long origId = Binder.clearCallingIdentity();
10698 serviceDoneExecutingLocked(r, inStopping);
10699 Binder.restoreCallingIdentity(origId);
10700 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010701 Slog.w(TAG, "Done executing unknown service from pid "
10702 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010703 }
10704 }
10705 }
10706
10707 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010708 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10709 + ": nesting=" + r.executeNesting
10710 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010711 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010712 r.executeNesting--;
10713 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010714 if (DEBUG_SERVICE) Slog.v(TAG,
10715 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010716 r.app.executingServices.remove(r);
10717 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010718 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10719 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010720 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10721 }
10722 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010723 if (DEBUG_SERVICE) Slog.v(TAG,
10724 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010725 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010726 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010727 }
10728 updateOomAdjLocked(r.app);
10729 }
10730 }
10731
10732 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010733 String anrMessage = null;
10734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010735 synchronized(this) {
10736 if (proc.executingServices.size() == 0 || proc.thread == null) {
10737 return;
10738 }
10739 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10740 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10741 ServiceRecord timeout = null;
10742 long nextTime = 0;
10743 while (it.hasNext()) {
10744 ServiceRecord sr = it.next();
10745 if (sr.executingStart < maxTime) {
10746 timeout = sr;
10747 break;
10748 }
10749 if (sr.executingStart > nextTime) {
10750 nextTime = sr.executingStart;
10751 }
10752 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010753 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010754 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010755 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010756 } else {
10757 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10758 msg.obj = proc;
10759 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10760 }
10761 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010762
10763 if (anrMessage != null) {
10764 appNotResponding(proc, null, null, anrMessage);
10765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010766 }
10767
10768 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010769 // BACKUP AND RESTORE
10770 // =========================================================
10771
10772 // Cause the target app to be launched if necessary and its backup agent
10773 // instantiated. The backup agent will invoke backupAgentCreated() on the
10774 // activity manager to announce its creation.
10775 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010776 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010777 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10778
10779 synchronized(this) {
10780 // !!! TODO: currently no check here that we're already bound
10781 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10782 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10783 synchronized (stats) {
10784 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10785 }
10786
Dianne Hackborne7f97212011-02-24 14:40:20 -080010787 // Backup agent is now in use, its package can't be stopped.
10788 try {
10789 AppGlobals.getPackageManager().setPackageStoppedState(
10790 app.packageName, false);
10791 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010792 } catch (IllegalArgumentException e) {
10793 Slog.w(TAG, "Failed trying to unstop package "
10794 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010795 }
10796
Christopher Tate181fafa2009-05-14 11:12:14 -070010797 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070010798 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
10799 ? new ComponentName(app.packageName, app.backupAgentName)
10800 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070010801 // startProcessLocked() returns existing proc's record if it's already running
10802 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010803 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010804 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010805 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010806 return false;
10807 }
10808
10809 r.app = proc;
10810 mBackupTarget = r;
10811 mBackupAppName = app.packageName;
10812
Christopher Tate6fa95972009-06-05 18:43:55 -070010813 // Try not to kill the process during backup
10814 updateOomAdjLocked(proc);
10815
Christopher Tate181fafa2009-05-14 11:12:14 -070010816 // If the process is already attached, schedule the creation of the backup agent now.
10817 // If it is not yet live, this will be done when it attaches to the framework.
10818 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010819 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010820 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010821 proc.thread.scheduleCreateBackupAgent(app,
10822 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010823 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010824 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010825 }
10826 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010827 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010828 }
10829 // Invariants: at this point, the target app process exists and the application
10830 // is either already running or in the process of coming up. mBackupTarget and
10831 // mBackupAppName describe the app, so that when it binds back to the AM we
10832 // know that it's scheduled for a backup-agent operation.
10833 }
10834
10835 return true;
10836 }
10837
10838 // A backup agent has just come up
10839 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010840 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010841 + " = " + agent);
10842
10843 synchronized(this) {
10844 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010845 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010846 return;
10847 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010848 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010849
Dianne Hackborn06740692010-09-22 22:46:21 -070010850 long oldIdent = Binder.clearCallingIdentity();
10851 try {
10852 IBackupManager bm = IBackupManager.Stub.asInterface(
10853 ServiceManager.getService(Context.BACKUP_SERVICE));
10854 bm.agentConnected(agentPackageName, agent);
10855 } catch (RemoteException e) {
10856 // can't happen; the backup manager service is local
10857 } catch (Exception e) {
10858 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10859 e.printStackTrace();
10860 } finally {
10861 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010862 }
10863 }
10864
10865 // done with this agent
10866 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010867 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010868 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010869 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010870 return;
10871 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010872
10873 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010874 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010875 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010876 return;
10877 }
10878
Christopher Tate181fafa2009-05-14 11:12:14 -070010879 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010880 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010881 return;
10882 }
10883
Christopher Tate6fa95972009-06-05 18:43:55 -070010884 ProcessRecord proc = mBackupTarget.app;
10885 mBackupTarget = null;
10886 mBackupAppName = null;
10887
10888 // Not backing this app up any more; reset its OOM adjustment
10889 updateOomAdjLocked(proc);
10890
Christopher Tatec7b31e32009-06-10 15:49:30 -070010891 // If the app crashed during backup, 'thread' will be null here
10892 if (proc.thread != null) {
10893 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010894 proc.thread.scheduleDestroyBackupAgent(appInfo,
10895 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070010896 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010897 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010898 e.printStackTrace();
10899 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010900 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010901 }
10902 }
10903 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010904 // BROADCASTS
10905 // =========================================================
10906
Josh Bartel7f208742010-02-25 11:01:44 -060010907 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010908 List cur) {
10909 final ContentResolver resolver = mContext.getContentResolver();
10910 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10911 if (list == null) {
10912 return cur;
10913 }
10914 int N = list.size();
10915 for (int i=0; i<N; i++) {
10916 Intent intent = list.get(i);
10917 if (filter.match(resolver, intent, true, TAG) >= 0) {
10918 if (cur == null) {
10919 cur = new ArrayList<Intent>();
10920 }
10921 cur.add(intent);
10922 }
10923 }
10924 return cur;
10925 }
10926
10927 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010928 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 + mBroadcastsScheduled);
10930
10931 if (mBroadcastsScheduled) {
10932 return;
10933 }
10934 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10935 mBroadcastsScheduled = true;
10936 }
10937
10938 public Intent registerReceiver(IApplicationThread caller,
10939 IIntentReceiver receiver, IntentFilter filter, String permission) {
10940 synchronized(this) {
10941 ProcessRecord callerApp = null;
10942 if (caller != null) {
10943 callerApp = getRecordForAppLocked(caller);
10944 if (callerApp == null) {
10945 throw new SecurityException(
10946 "Unable to find app for caller " + caller
10947 + " (pid=" + Binder.getCallingPid()
10948 + ") when registering receiver " + receiver);
10949 }
10950 }
10951
10952 List allSticky = null;
10953
10954 // Look for any matching sticky broadcasts...
10955 Iterator actions = filter.actionsIterator();
10956 if (actions != null) {
10957 while (actions.hasNext()) {
10958 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010959 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 }
10961 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010962 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 }
10964
10965 // The first sticky in the list is returned directly back to
10966 // the client.
10967 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10968
Joe Onorato8a9b2202010-02-26 18:56:32 -080010969 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010970 + ": " + sticky);
10971
10972 if (receiver == null) {
10973 return sticky;
10974 }
10975
10976 ReceiverList rl
10977 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10978 if (rl == null) {
10979 rl = new ReceiverList(this, callerApp,
10980 Binder.getCallingPid(),
10981 Binder.getCallingUid(), receiver);
10982 if (rl.app != null) {
10983 rl.app.receivers.add(rl);
10984 } else {
10985 try {
10986 receiver.asBinder().linkToDeath(rl, 0);
10987 } catch (RemoteException e) {
10988 return sticky;
10989 }
10990 rl.linkedToDeath = true;
10991 }
10992 mRegisteredReceivers.put(receiver.asBinder(), rl);
10993 }
10994 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10995 rl.add(bf);
10996 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010997 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010998 }
10999 mReceiverResolver.addFilter(bf);
11000
11001 // Enqueue broadcasts for all existing stickies that match
11002 // this filter.
11003 if (allSticky != null) {
11004 ArrayList receivers = new ArrayList();
11005 receivers.add(bf);
11006
11007 int N = allSticky.size();
11008 for (int i=0; i<N; i++) {
11009 Intent intent = (Intent)allSticky.get(i);
11010 BroadcastRecord r = new BroadcastRecord(intent, null,
11011 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011012 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011013 if (mParallelBroadcasts.size() == 0) {
11014 scheduleBroadcastsLocked();
11015 }
11016 mParallelBroadcasts.add(r);
11017 }
11018 }
11019
11020 return sticky;
11021 }
11022 }
11023
11024 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011025 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011026
11027 boolean doNext = false;
11028
11029 synchronized(this) {
11030 ReceiverList rl
11031 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11032 if (rl != null) {
11033 if (rl.curBroadcast != null) {
11034 BroadcastRecord r = rl.curBroadcast;
11035 doNext = finishReceiverLocked(
11036 receiver.asBinder(), r.resultCode, r.resultData,
11037 r.resultExtras, r.resultAbort, true);
11038 }
11039
11040 if (rl.app != null) {
11041 rl.app.receivers.remove(rl);
11042 }
11043 removeReceiverLocked(rl);
11044 if (rl.linkedToDeath) {
11045 rl.linkedToDeath = false;
11046 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11047 }
11048 }
11049 }
11050
11051 if (!doNext) {
11052 return;
11053 }
11054
11055 final long origId = Binder.clearCallingIdentity();
11056 processNextBroadcast(false);
11057 trimApplications();
11058 Binder.restoreCallingIdentity(origId);
11059 }
11060
11061 void removeReceiverLocked(ReceiverList rl) {
11062 mRegisteredReceivers.remove(rl.receiver.asBinder());
11063 int N = rl.size();
11064 for (int i=0; i<N; i++) {
11065 mReceiverResolver.removeFilter(rl.get(i));
11066 }
11067 }
11068
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011069 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
11070 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11071 ProcessRecord r = mLruProcesses.get(i);
11072 if (r.thread != null) {
11073 try {
11074 r.thread.dispatchPackageBroadcast(cmd, packages);
11075 } catch (RemoteException ex) {
11076 }
11077 }
11078 }
11079 }
11080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011081 private final int broadcastIntentLocked(ProcessRecord callerApp,
11082 String callerPackage, Intent intent, String resolvedType,
11083 IIntentReceiver resultTo, int resultCode, String resultData,
11084 Bundle map, String requiredPermission,
11085 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11086 intent = new Intent(intent);
11087
Dianne Hackborne7f97212011-02-24 14:40:20 -080011088 // By default broadcasts do not go to stopped apps.
11089 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
11090
Joe Onorato8a9b2202010-02-26 18:56:32 -080011091 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011092 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11093 + " ordered=" + ordered);
11094 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011095 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011096 }
11097
11098 // Handle special intents: if this broadcast is from the package
11099 // manager about a package being removed, we need to remove all of
11100 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011101 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011102 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011103 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11104 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011105 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011106 || uidRemoved) {
11107 if (checkComponentPermission(
11108 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011109 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 == PackageManager.PERMISSION_GRANTED) {
11111 if (uidRemoved) {
11112 final Bundle intentExtras = intent.getExtras();
11113 final int uid = intentExtras != null
11114 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11115 if (uid >= 0) {
11116 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11117 synchronized (bs) {
11118 bs.removeUidStatsLocked(uid);
11119 }
11120 }
11121 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011122 // If resources are unvailble just force stop all
11123 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011124 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011125 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11126 if (list != null && (list.length > 0)) {
11127 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011128 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011129 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011130 sendPackageBroadcastLocked(
11131 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011132 }
11133 } else {
11134 Uri data = intent.getData();
11135 String ssp;
11136 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11137 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11138 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011139 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011140 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011141 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011142 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
11143 new String[] {ssp});
11144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 }
11146 }
11147 }
11148 } else {
11149 String msg = "Permission Denial: " + intent.getAction()
11150 + " broadcast from " + callerPackage + " (pid=" + callingPid
11151 + ", uid=" + callingUid + ")"
11152 + " requires "
11153 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011154 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011155 throw new SecurityException(msg);
11156 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011157
11158 // Special case for adding a package: by default turn on compatibility
11159 // mode.
11160 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
11161 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
11162 Uri data = intent.getData();
11163 String ssp;
11164 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11165 mCompatModePackages.setPackageScreenCompatModeLocked(ssp,
11166 ActivityManager.COMPAT_MODE_ENABLED);
11167 }
11168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011169 }
11170
11171 /*
11172 * If this is the time zone changed action, queue up a message that will reset the timezone
11173 * of all currently running processes. This message will get queued up before the broadcast
11174 * happens.
11175 */
11176 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11177 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11178 }
11179
Robert Greenwalt03595d02010-11-02 14:08:23 -070011180 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
11181 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
11182 }
11183
Robert Greenwalt434203a2010-10-11 16:00:27 -070011184 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
11185 ProxyProperties proxy = intent.getParcelableExtra("proxy");
11186 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
11187 }
11188
Dianne Hackborn854060af2009-07-09 18:14:31 -070011189 /*
11190 * Prevent non-system code (defined here to be non-persistent
11191 * processes) from sending protected broadcasts.
11192 */
11193 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11194 || callingUid == Process.SHELL_UID || callingUid == 0) {
11195 // Always okay.
11196 } else if (callerApp == null || !callerApp.persistent) {
11197 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011198 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070011199 intent.getAction())) {
11200 String msg = "Permission Denial: not allowed to send broadcast "
11201 + intent.getAction() + " from pid="
11202 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011203 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011204 throw new SecurityException(msg);
11205 }
11206 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011207 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011208 return BROADCAST_SUCCESS;
11209 }
11210 }
11211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011212 // Add to the sticky list if requested.
11213 if (sticky) {
11214 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11215 callingPid, callingUid)
11216 != PackageManager.PERMISSION_GRANTED) {
11217 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11218 + callingPid + ", uid=" + callingUid
11219 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011220 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011221 throw new SecurityException(msg);
11222 }
11223 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011224 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011225 + " and enforce permission " + requiredPermission);
11226 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11227 }
11228 if (intent.getComponent() != null) {
11229 throw new SecurityException(
11230 "Sticky broadcasts can't target a specific component");
11231 }
11232 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11233 if (list == null) {
11234 list = new ArrayList<Intent>();
11235 mStickyBroadcasts.put(intent.getAction(), list);
11236 }
11237 int N = list.size();
11238 int i;
11239 for (i=0; i<N; i++) {
11240 if (intent.filterEquals(list.get(i))) {
11241 // This sticky already exists, replace it.
11242 list.set(i, new Intent(intent));
11243 break;
11244 }
11245 }
11246 if (i >= N) {
11247 list.add(new Intent(intent));
11248 }
11249 }
11250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011251 // Figure out who all will receive this broadcast.
11252 List receivers = null;
11253 List<BroadcastFilter> registeredReceivers = null;
11254 try {
11255 if (intent.getComponent() != null) {
11256 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011257 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011258 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011259 if (ai != null) {
11260 receivers = new ArrayList();
11261 ResolveInfo ri = new ResolveInfo();
11262 ri.activityInfo = ai;
11263 receivers.add(ri);
11264 }
11265 } else {
11266 // Need to resolve the intent to interested receivers...
11267 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11268 == 0) {
11269 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011270 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011271 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011272 }
Mihai Preda074edef2009-05-18 17:13:31 +020011273 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 }
11275 } catch (RemoteException ex) {
11276 // pm is in same process, this will never happen.
11277 }
11278
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011279 final boolean replacePending =
11280 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11281
Joe Onorato8a9b2202010-02-26 18:56:32 -080011282 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011283 + " replacePending=" + replacePending);
11284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11286 if (!ordered && NR > 0) {
11287 // If we are not serializing this broadcast, then send the
11288 // registered receivers separately so they don't wait for the
11289 // components to be launched.
11290 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11291 callerPackage, callingPid, callingUid, requiredPermission,
11292 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011293 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011294 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 TAG, "Enqueueing parallel broadcast " + r
11296 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011297 boolean replaced = false;
11298 if (replacePending) {
11299 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11300 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011301 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011302 "***** DROPPING PARALLEL: " + intent);
11303 mParallelBroadcasts.set(i, r);
11304 replaced = true;
11305 break;
11306 }
11307 }
11308 }
11309 if (!replaced) {
11310 mParallelBroadcasts.add(r);
11311 scheduleBroadcastsLocked();
11312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011313 registeredReceivers = null;
11314 NR = 0;
11315 }
11316
11317 // Merge into one list.
11318 int ir = 0;
11319 if (receivers != null) {
11320 // A special case for PACKAGE_ADDED: do not allow the package
11321 // being added to see this broadcast. This prevents them from
11322 // using this as a back door to get run as soon as they are
11323 // installed. Maybe in the future we want to have a special install
11324 // broadcast or such for apps, but we'd like to deliberately make
11325 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011326 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011327 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11328 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11329 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011330 Uri data = intent.getData();
11331 if (data != null) {
11332 String pkgName = data.getSchemeSpecificPart();
11333 if (pkgName != null) {
11334 skipPackages = new String[] { pkgName };
11335 }
11336 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011337 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011338 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011339 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011340 if (skipPackages != null && (skipPackages.length > 0)) {
11341 for (String skipPackage : skipPackages) {
11342 if (skipPackage != null) {
11343 int NT = receivers.size();
11344 for (int it=0; it<NT; it++) {
11345 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11346 if (curt.activityInfo.packageName.equals(skipPackage)) {
11347 receivers.remove(it);
11348 it--;
11349 NT--;
11350 }
11351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011352 }
11353 }
11354 }
11355
11356 int NT = receivers != null ? receivers.size() : 0;
11357 int it = 0;
11358 ResolveInfo curt = null;
11359 BroadcastFilter curr = null;
11360 while (it < NT && ir < NR) {
11361 if (curt == null) {
11362 curt = (ResolveInfo)receivers.get(it);
11363 }
11364 if (curr == null) {
11365 curr = registeredReceivers.get(ir);
11366 }
11367 if (curr.getPriority() >= curt.priority) {
11368 // Insert this broadcast record into the final list.
11369 receivers.add(it, curr);
11370 ir++;
11371 curr = null;
11372 it++;
11373 NT++;
11374 } else {
11375 // Skip to the next ResolveInfo in the final list.
11376 it++;
11377 curt = null;
11378 }
11379 }
11380 }
11381 while (ir < NR) {
11382 if (receivers == null) {
11383 receivers = new ArrayList();
11384 }
11385 receivers.add(registeredReceivers.get(ir));
11386 ir++;
11387 }
11388
11389 if ((receivers != null && receivers.size() > 0)
11390 || resultTo != null) {
11391 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11392 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011393 receivers, resultTo, resultCode, resultData, map, ordered,
11394 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011395 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011396 TAG, "Enqueueing ordered broadcast " + r
11397 + ": prev had " + mOrderedBroadcasts.size());
11398 if (DEBUG_BROADCAST) {
11399 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011400 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011401 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011402 boolean replaced = false;
11403 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011404 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011405 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011406 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011407 "***** DROPPING ORDERED: " + intent);
11408 mOrderedBroadcasts.set(i, r);
11409 replaced = true;
11410 break;
11411 }
11412 }
11413 }
11414 if (!replaced) {
11415 mOrderedBroadcasts.add(r);
11416 scheduleBroadcastsLocked();
11417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418 }
11419
11420 return BROADCAST_SUCCESS;
11421 }
11422
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011423 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011424 // Refuse possible leaked file descriptors
11425 if (intent != null && intent.hasFileDescriptors() == true) {
11426 throw new IllegalArgumentException("File descriptors passed in Intent");
11427 }
11428
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011429 int flags = intent.getFlags();
11430
11431 if (!mProcessesReady) {
11432 // if the caller really truly claims to know what they're doing, go
11433 // ahead and allow the broadcast without launching any receivers
11434 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11435 intent = new Intent(intent);
11436 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11437 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11438 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11439 + " before boot completion");
11440 throw new IllegalStateException("Cannot broadcast before boot completed");
11441 }
11442 }
11443
11444 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11445 throw new IllegalArgumentException(
11446 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11447 }
11448
11449 return intent;
11450 }
11451
11452 public final int broadcastIntent(IApplicationThread caller,
11453 Intent intent, String resolvedType, IIntentReceiver resultTo,
11454 int resultCode, String resultData, Bundle map,
11455 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011456 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011457 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011459 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11460 final int callingPid = Binder.getCallingPid();
11461 final int callingUid = Binder.getCallingUid();
11462 final long origId = Binder.clearCallingIdentity();
11463 int res = broadcastIntentLocked(callerApp,
11464 callerApp != null ? callerApp.info.packageName : null,
11465 intent, resolvedType, resultTo,
11466 resultCode, resultData, map, requiredPermission, serialized,
11467 sticky, callingPid, callingUid);
11468 Binder.restoreCallingIdentity(origId);
11469 return res;
11470 }
11471 }
11472
11473 int broadcastIntentInPackage(String packageName, int uid,
11474 Intent intent, String resolvedType, IIntentReceiver resultTo,
11475 int resultCode, String resultData, Bundle map,
11476 String requiredPermission, boolean serialized, boolean sticky) {
11477 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011478 intent = verifyBroadcastLocked(intent);
11479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011480 final long origId = Binder.clearCallingIdentity();
11481 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11482 resultTo, resultCode, resultData, map, requiredPermission,
11483 serialized, sticky, -1, uid);
11484 Binder.restoreCallingIdentity(origId);
11485 return res;
11486 }
11487 }
11488
11489 public final void unbroadcastIntent(IApplicationThread caller,
11490 Intent intent) {
11491 // Refuse possible leaked file descriptors
11492 if (intent != null && intent.hasFileDescriptors() == true) {
11493 throw new IllegalArgumentException("File descriptors passed in Intent");
11494 }
11495
11496 synchronized(this) {
11497 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11498 != PackageManager.PERMISSION_GRANTED) {
11499 String msg = "Permission Denial: unbroadcastIntent() from pid="
11500 + Binder.getCallingPid()
11501 + ", uid=" + Binder.getCallingUid()
11502 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011503 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011504 throw new SecurityException(msg);
11505 }
11506 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11507 if (list != null) {
11508 int N = list.size();
11509 int i;
11510 for (i=0; i<N; i++) {
11511 if (intent.filterEquals(list.get(i))) {
11512 list.remove(i);
11513 break;
11514 }
11515 }
11516 }
11517 }
11518 }
11519
11520 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11521 String resultData, Bundle resultExtras, boolean resultAbort,
11522 boolean explicit) {
11523 if (mOrderedBroadcasts.size() == 0) {
11524 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011525 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011526 }
11527 return false;
11528 }
11529 BroadcastRecord r = mOrderedBroadcasts.get(0);
11530 if (r.receiver == null) {
11531 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011532 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011533 }
11534 return false;
11535 }
11536 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011537 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011538 return false;
11539 }
11540 int state = r.state;
11541 r.state = r.IDLE;
11542 if (state == r.IDLE) {
11543 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011544 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011545 }
11546 }
11547 r.receiver = null;
11548 r.intent.setComponent(null);
11549 if (r.curApp != null) {
11550 r.curApp.curReceiver = null;
11551 }
11552 if (r.curFilter != null) {
11553 r.curFilter.receiverList.curBroadcast = null;
11554 }
11555 r.curFilter = null;
11556 r.curApp = null;
11557 r.curComponent = null;
11558 r.curReceiver = null;
11559 mPendingBroadcast = null;
11560
11561 r.resultCode = resultCode;
11562 r.resultData = resultData;
11563 r.resultExtras = resultExtras;
11564 r.resultAbort = resultAbort;
11565
11566 // We will process the next receiver right now if this is finishing
11567 // an app receiver (which is always asynchronous) or after we have
11568 // come back from calling a receiver.
11569 return state == BroadcastRecord.APP_RECEIVE
11570 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11571 }
11572
11573 public void finishReceiver(IBinder who, int resultCode, String resultData,
11574 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011575 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576
11577 // Refuse possible leaked file descriptors
11578 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11579 throw new IllegalArgumentException("File descriptors passed in Bundle");
11580 }
11581
11582 boolean doNext;
11583
11584 final long origId = Binder.clearCallingIdentity();
11585
11586 synchronized(this) {
11587 doNext = finishReceiverLocked(
11588 who, resultCode, resultData, resultExtras, resultAbort, true);
11589 }
11590
11591 if (doNext) {
11592 processNextBroadcast(false);
11593 }
11594 trimApplications();
11595
11596 Binder.restoreCallingIdentity(origId);
11597 }
11598
Jeff Brown4d94a762010-09-23 11:33:28 -070011599 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011600 if (r.nextReceiver > 0) {
11601 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11602 if (curReceiver instanceof BroadcastFilter) {
11603 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011604 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011605 System.identityHashCode(r),
11606 r.intent.getAction(),
11607 r.nextReceiver - 1,
11608 System.identityHashCode(bf));
11609 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011610 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011611 System.identityHashCode(r),
11612 r.intent.getAction(),
11613 r.nextReceiver - 1,
11614 ((ResolveInfo)curReceiver).toString());
11615 }
11616 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011617 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011618 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011619 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620 System.identityHashCode(r),
11621 r.intent.getAction(),
11622 r.nextReceiver,
11623 "NONE");
11624 }
11625 }
11626
Jeff Brown4d94a762010-09-23 11:33:28 -070011627 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11628 if (! mPendingBroadcastTimeoutMessage) {
11629 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11630 mHandler.sendMessageAtTime(msg, timeoutTime);
11631 mPendingBroadcastTimeoutMessage = true;
11632 }
11633 }
11634
11635 private final void cancelBroadcastTimeoutLocked() {
11636 if (mPendingBroadcastTimeoutMessage) {
11637 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11638 mPendingBroadcastTimeoutMessage = false;
11639 }
11640 }
11641
11642 private final void broadcastTimeoutLocked(boolean fromMsg) {
11643 if (fromMsg) {
11644 mPendingBroadcastTimeoutMessage = false;
11645 }
11646
11647 if (mOrderedBroadcasts.size() == 0) {
11648 return;
11649 }
11650
11651 long now = SystemClock.uptimeMillis();
11652 BroadcastRecord r = mOrderedBroadcasts.get(0);
11653 if (fromMsg) {
11654 if (mDidDexOpt) {
11655 // Delay timeouts until dexopt finishes.
11656 mDidDexOpt = false;
11657 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11658 setBroadcastTimeoutLocked(timeoutTime);
11659 return;
11660 }
11661 if (! mProcessesReady) {
11662 // Only process broadcast timeouts if the system is ready. That way
11663 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11664 // to do heavy lifting for system up.
11665 return;
11666 }
11667
11668 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11669 if (timeoutTime > now) {
11670 // We can observe premature timeouts because we do not cancel and reset the
11671 // broadcast timeout message after each receiver finishes. Instead, we set up
11672 // an initial timeout then kick it down the road a little further as needed
11673 // when it expires.
11674 if (DEBUG_BROADCAST) Slog.v(TAG,
11675 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11676 + timeoutTime);
11677 setBroadcastTimeoutLocked(timeoutTime);
11678 return;
11679 }
11680 }
11681
11682 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11683 + ", started " + (now - r.receiverTime) + "ms ago");
11684 r.receiverTime = now;
11685 r.anrCount++;
11686
11687 // Current receiver has passed its expiration date.
11688 if (r.nextReceiver <= 0) {
11689 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11690 return;
11691 }
11692
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011693 ProcessRecord app = null;
11694 String anrMessage = null;
11695
Jeff Brown4d94a762010-09-23 11:33:28 -070011696 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11697 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11698 logBroadcastReceiverDiscardLocked(r);
11699 if (curReceiver instanceof BroadcastFilter) {
11700 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11701 if (bf.receiverList.pid != 0
11702 && bf.receiverList.pid != MY_PID) {
11703 synchronized (this.mPidsSelfLocked) {
11704 app = this.mPidsSelfLocked.get(
11705 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011707 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011708 } else {
11709 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011710 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011711
Jeff Brown4d94a762010-09-23 11:33:28 -070011712 if (app != null) {
11713 anrMessage = "Broadcast of " + r.intent.toString();
11714 }
11715
11716 if (mPendingBroadcast == r) {
11717 mPendingBroadcast = null;
11718 }
11719
11720 // Move on to the next receiver.
11721 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11722 r.resultExtras, r.resultAbort, true);
11723 scheduleBroadcastsLocked();
11724
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011725 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011726 // Post the ANR to the handler since we do not want to process ANRs while
11727 // potentially holding our lock.
11728 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011730 }
11731
11732 private final void processCurBroadcastLocked(BroadcastRecord r,
11733 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011734 if (DEBUG_BROADCAST) Slog.v(TAG,
11735 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011736 if (app.thread == null) {
11737 throw new RemoteException();
11738 }
11739 r.receiver = app.thread.asBinder();
11740 r.curApp = app;
11741 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011742 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011743
11744 // Tell the application to launch this receiver.
11745 r.intent.setComponent(r.curComponent);
11746
11747 boolean started = false;
11748 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011749 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011750 "Delivering to component " + r.curComponent
11751 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011752 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011753 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011754 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011755 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011756 if (DEBUG_BROADCAST) Slog.v(TAG,
11757 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011758 started = true;
11759 } finally {
11760 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011761 if (DEBUG_BROADCAST) Slog.v(TAG,
11762 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763 r.receiver = null;
11764 r.curApp = null;
11765 app.curReceiver = null;
11766 }
11767 }
11768
11769 }
11770
Jeff Brown4d94a762010-09-23 11:33:28 -070011771 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011772 Intent intent, int resultCode, String data, Bundle extras,
11773 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011774 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011775 if (app != null && app.thread != null) {
11776 // If we have an app thread, do the call through that so it is
11777 // correctly ordered with other one-way calls.
11778 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011779 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011780 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011781 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011782 }
11783 }
11784
Jeff Brown4d94a762010-09-23 11:33:28 -070011785 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011786 BroadcastFilter filter, boolean ordered) {
11787 boolean skip = false;
11788 if (filter.requiredPermission != null) {
11789 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011790 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011791 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011792 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011793 + r.intent.toString()
11794 + " from " + r.callerPackage + " (pid="
11795 + r.callingPid + ", uid=" + r.callingUid + ")"
11796 + " requires " + filter.requiredPermission
11797 + " due to registered receiver " + filter);
11798 skip = true;
11799 }
11800 }
11801 if (r.requiredPermission != null) {
11802 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011803 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011805 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011806 + r.intent.toString()
11807 + " to " + filter.receiverList.app
11808 + " (pid=" + filter.receiverList.pid
11809 + ", uid=" + filter.receiverList.uid + ")"
11810 + " requires " + r.requiredPermission
11811 + " due to sender " + r.callerPackage
11812 + " (uid " + r.callingUid + ")");
11813 skip = true;
11814 }
11815 }
11816
11817 if (!skip) {
11818 // If this is not being sent as an ordered broadcast, then we
11819 // don't want to touch the fields that keep track of the current
11820 // state of ordered broadcasts.
11821 if (ordered) {
11822 r.receiver = filter.receiverList.receiver.asBinder();
11823 r.curFilter = filter;
11824 filter.receiverList.curBroadcast = r;
11825 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011826 if (filter.receiverList.app != null) {
11827 // Bump hosting application to no longer be in background
11828 // scheduling class. Note that we can't do that if there
11829 // isn't an app... but we can only be in that case for
11830 // things that directly call the IActivityManager API, which
11831 // are already core system stuff so don't matter for this.
11832 r.curApp = filter.receiverList.app;
11833 filter.receiverList.app.curReceiver = r;
11834 updateOomAdjLocked();
11835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011836 }
11837 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011838 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011839 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011840 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011841 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011842 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011843 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011844 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011845 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 if (ordered) {
11847 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11848 }
11849 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011850 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011851 if (ordered) {
11852 r.receiver = null;
11853 r.curFilter = null;
11854 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011855 if (filter.receiverList.app != null) {
11856 filter.receiverList.app.curReceiver = null;
11857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011858 }
11859 }
11860 }
11861 }
11862
Dianne Hackborn12527f92009-11-11 17:39:50 -080011863 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11864 if (r.callingUid < 0) {
11865 // This was from a registerReceiver() call; ignore it.
11866 return;
11867 }
11868 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11869 MAX_BROADCAST_HISTORY-1);
11870 r.finishTime = SystemClock.uptimeMillis();
11871 mBroadcastHistory[0] = r;
11872 }
11873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011874 private final void processNextBroadcast(boolean fromMsg) {
11875 synchronized(this) {
11876 BroadcastRecord r;
11877
Joe Onorato8a9b2202010-02-26 18:56:32 -080011878 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011879 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011880 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011881
11882 updateCpuStats();
11883
11884 if (fromMsg) {
11885 mBroadcastsScheduled = false;
11886 }
11887
11888 // First, deliver any non-serialized broadcasts right away.
11889 while (mParallelBroadcasts.size() > 0) {
11890 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011891 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011892 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011893 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011894 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011895 for (int i=0; i<N; i++) {
11896 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011897 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011898 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011899 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011900 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011901 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011902 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011903 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011904 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011905 }
11906
11907 // Now take care of the next serialized one...
11908
11909 // If we are waiting for a process to come up to handle the next
11910 // broadcast, then do nothing at this point. Just in case, we
11911 // check that the process we're waiting for still exists.
11912 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011913 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011914 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011915 + mPendingBroadcast.curApp);
11916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011917
11918 boolean isDead;
11919 synchronized (mPidsSelfLocked) {
11920 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11921 }
11922 if (!isDead) {
11923 // It's still alive, so keep waiting
11924 return;
11925 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011926 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011927 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011928 mPendingBroadcast.state = BroadcastRecord.IDLE;
11929 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011930 mPendingBroadcast = null;
11931 }
11932 }
11933
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011934 boolean looped = false;
11935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011936 do {
11937 if (mOrderedBroadcasts.size() == 0) {
11938 // No more broadcasts pending, so all done!
11939 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011940 if (looped) {
11941 // If we had finished the last ordered broadcast, then
11942 // make sure all processes have correct oom and sched
11943 // adjustments.
11944 updateOomAdjLocked();
11945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011946 return;
11947 }
11948 r = mOrderedBroadcasts.get(0);
11949 boolean forceReceive = false;
11950
11951 // Ensure that even if something goes awry with the timeout
11952 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011953 // and continue to make progress.
11954 //
11955 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011956 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011957 // one time heavy lifting after system upgrades and can take
11958 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011959 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011960 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011961 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011962 if ((numReceivers > 0) &&
11963 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011964 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011965 + " now=" + now
11966 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011967 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011968 + " intent=" + r.intent
11969 + " numReceivers=" + numReceivers
11970 + " nextReceiver=" + r.nextReceiver
11971 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011972 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011973 forceReceive = true;
11974 r.state = BroadcastRecord.IDLE;
11975 }
11976 }
11977
11978 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011979 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011980 "processNextBroadcast() called when not idle (state="
11981 + r.state + ")");
11982 return;
11983 }
11984
11985 if (r.receivers == null || r.nextReceiver >= numReceivers
11986 || r.resultAbort || forceReceive) {
11987 // No more receivers for this broadcast! Send the final
11988 // result if requested...
11989 if (r.resultTo != null) {
11990 try {
11991 if (DEBUG_BROADCAST) {
11992 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011993 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011994 + " seq=" + seq + " app=" + r.callerApp);
11995 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011996 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011997 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011998 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011999 // Set this to null so that the reference
12000 // (local and remote) isnt kept in the mBroadcastHistory.
12001 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012002 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012003 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012004 }
12005 }
12006
Joe Onorato8a9b2202010-02-26 18:56:32 -080012007 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070012008 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012009
Joe Onorato8a9b2202010-02-26 18:56:32 -080012010 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012011 + r);
12012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012013 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012014 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012015 mOrderedBroadcasts.remove(0);
12016 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012017 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012018 continue;
12019 }
12020 } while (r == null);
12021
12022 // Get the next receiver...
12023 int recIdx = r.nextReceiver++;
12024
12025 // Keep track of when this receiver started, and make sure there
12026 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012027 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012028 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012029 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012030
Joe Onorato8a9b2202010-02-26 18:56:32 -080012031 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012032 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012033 }
12034 if (! mPendingBroadcastTimeoutMessage) {
12035 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012036 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070012037 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
12038 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012039 }
12040
12041 Object nextReceiver = r.receivers.get(recIdx);
12042 if (nextReceiver instanceof BroadcastFilter) {
12043 // Simple case: this is a registered receiver who gets
12044 // a direct call.
12045 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012046 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012047 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012048 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012049 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012050 if (r.receiver == null || !r.ordered) {
12051 // The receiver has already finished, so schedule to
12052 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012053 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
12054 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012055 r.state = BroadcastRecord.IDLE;
12056 scheduleBroadcastsLocked();
12057 }
12058 return;
12059 }
12060
12061 // Hard case: need to instantiate the receiver, possibly
12062 // starting its application process to host it.
12063
12064 ResolveInfo info =
12065 (ResolveInfo)nextReceiver;
12066
12067 boolean skip = false;
12068 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012069 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
12070 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012071 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012072 if (!info.activityInfo.exported) {
12073 Slog.w(TAG, "Permission Denial: broadcasting "
12074 + r.intent.toString()
12075 + " from " + r.callerPackage + " (pid=" + r.callingPid
12076 + ", uid=" + r.callingUid + ")"
12077 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
12078 + " due to receiver " + info.activityInfo.packageName
12079 + "/" + info.activityInfo.name);
12080 } else {
12081 Slog.w(TAG, "Permission Denial: broadcasting "
12082 + r.intent.toString()
12083 + " from " + r.callerPackage + " (pid=" + r.callingPid
12084 + ", uid=" + r.callingUid + ")"
12085 + " requires " + info.activityInfo.permission
12086 + " due to receiver " + info.activityInfo.packageName
12087 + "/" + info.activityInfo.name);
12088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089 skip = true;
12090 }
12091 if (r.callingUid != Process.SYSTEM_UID &&
12092 r.requiredPermission != null) {
12093 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012094 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012095 checkPermission(r.requiredPermission,
12096 info.activityInfo.applicationInfo.packageName);
12097 } catch (RemoteException e) {
12098 perm = PackageManager.PERMISSION_DENIED;
12099 }
12100 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012101 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012102 + r.intent + " to "
12103 + info.activityInfo.applicationInfo.packageName
12104 + " requires " + r.requiredPermission
12105 + " due to sender " + r.callerPackage
12106 + " (uid " + r.callingUid + ")");
12107 skip = true;
12108 }
12109 }
12110 if (r.curApp != null && r.curApp.crashing) {
12111 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012112 if (DEBUG_BROADCAST) Slog.v(TAG,
12113 "Skipping deliver ordered " + r + " to " + r.curApp
12114 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012115 skip = true;
12116 }
12117
12118 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012119 if (DEBUG_BROADCAST) Slog.v(TAG,
12120 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012121 r.receiver = null;
12122 r.curFilter = null;
12123 r.state = BroadcastRecord.IDLE;
12124 scheduleBroadcastsLocked();
12125 return;
12126 }
12127
12128 r.state = BroadcastRecord.APP_RECEIVE;
12129 String targetProcess = info.activityInfo.processName;
12130 r.curComponent = new ComponentName(
12131 info.activityInfo.applicationInfo.packageName,
12132 info.activityInfo.name);
12133 r.curReceiver = info.activityInfo;
12134
Dianne Hackborne7f97212011-02-24 14:40:20 -080012135 // Broadcast is being executed, its package can't be stopped.
12136 try {
12137 AppGlobals.getPackageManager().setPackageStoppedState(
12138 r.curComponent.getPackageName(), false);
12139 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012140 } catch (IllegalArgumentException e) {
12141 Slog.w(TAG, "Failed trying to unstop package "
12142 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012143 }
12144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012145 // Is this receiver's application already running?
12146 ProcessRecord app = getProcessRecordLocked(targetProcess,
12147 info.activityInfo.applicationInfo.uid);
12148 if (app != null && app.thread != null) {
12149 try {
12150 processCurBroadcastLocked(r, app);
12151 return;
12152 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012153 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012154 + r.curComponent, e);
12155 }
12156
12157 // If a dead object exception was thrown -- fall through to
12158 // restart the application.
12159 }
12160
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012161 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012162 if (DEBUG_BROADCAST) Slog.v(TAG,
12163 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012164 if ((r.curApp=startProcessLocked(targetProcess,
12165 info.activityInfo.applicationInfo, true,
12166 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012167 "broadcast", r.curComponent,
12168 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12169 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012170 // Ah, this recipient is unavailable. Finish it if necessary,
12171 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012172 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012173 + info.activityInfo.applicationInfo.packageName + "/"
12174 + info.activityInfo.applicationInfo.uid + " for broadcast "
12175 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070012176 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012177 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12178 r.resultExtras, r.resultAbort, true);
12179 scheduleBroadcastsLocked();
12180 r.state = BroadcastRecord.IDLE;
12181 return;
12182 }
12183
12184 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012185 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012186 }
12187 }
12188
12189 // =========================================================
12190 // INSTRUMENTATION
12191 // =========================================================
12192
12193 public boolean startInstrumentation(ComponentName className,
12194 String profileFile, int flags, Bundle arguments,
12195 IInstrumentationWatcher watcher) {
12196 // Refuse possible leaked file descriptors
12197 if (arguments != null && arguments.hasFileDescriptors()) {
12198 throw new IllegalArgumentException("File descriptors passed in Bundle");
12199 }
12200
12201 synchronized(this) {
12202 InstrumentationInfo ii = null;
12203 ApplicationInfo ai = null;
12204 try {
12205 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012206 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012207 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012208 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012209 } catch (PackageManager.NameNotFoundException e) {
12210 }
12211 if (ii == null) {
12212 reportStartInstrumentationFailure(watcher, className,
12213 "Unable to find instrumentation info for: " + className);
12214 return false;
12215 }
12216 if (ai == null) {
12217 reportStartInstrumentationFailure(watcher, className,
12218 "Unable to find instrumentation target package: " + ii.targetPackage);
12219 return false;
12220 }
12221
12222 int match = mContext.getPackageManager().checkSignatures(
12223 ii.targetPackage, ii.packageName);
12224 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12225 String msg = "Permission Denial: starting instrumentation "
12226 + className + " from pid="
12227 + Binder.getCallingPid()
12228 + ", uid=" + Binder.getCallingPid()
12229 + " not allowed because package " + ii.packageName
12230 + " does not have a signature matching the target "
12231 + ii.targetPackage;
12232 reportStartInstrumentationFailure(watcher, className, msg);
12233 throw new SecurityException(msg);
12234 }
12235
12236 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012237 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012238 ProcessRecord app = addAppLocked(ai);
12239 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012240 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012241 app.instrumentationProfileFile = profileFile;
12242 app.instrumentationArguments = arguments;
12243 app.instrumentationWatcher = watcher;
12244 app.instrumentationResultClass = className;
12245 Binder.restoreCallingIdentity(origId);
12246 }
12247
12248 return true;
12249 }
12250
12251 /**
12252 * Report errors that occur while attempting to start Instrumentation. Always writes the
12253 * error to the logs, but if somebody is watching, send the report there too. This enables
12254 * the "am" command to report errors with more information.
12255 *
12256 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12257 * @param cn The component name of the instrumentation.
12258 * @param report The error report.
12259 */
12260 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12261 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012262 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012263 try {
12264 if (watcher != null) {
12265 Bundle results = new Bundle();
12266 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12267 results.putString("Error", report);
12268 watcher.instrumentationStatus(cn, -1, results);
12269 }
12270 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012271 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012272 }
12273 }
12274
12275 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12276 if (app.instrumentationWatcher != null) {
12277 try {
12278 // NOTE: IInstrumentationWatcher *must* be oneway here
12279 app.instrumentationWatcher.instrumentationFinished(
12280 app.instrumentationClass,
12281 resultCode,
12282 results);
12283 } catch (RemoteException e) {
12284 }
12285 }
12286 app.instrumentationWatcher = null;
12287 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012288 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012289 app.instrumentationProfileFile = null;
12290 app.instrumentationArguments = null;
12291
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012292 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012293 }
12294
12295 public void finishInstrumentation(IApplicationThread target,
12296 int resultCode, Bundle results) {
12297 // Refuse possible leaked file descriptors
12298 if (results != null && results.hasFileDescriptors()) {
12299 throw new IllegalArgumentException("File descriptors passed in Intent");
12300 }
12301
12302 synchronized(this) {
12303 ProcessRecord app = getRecordForAppLocked(target);
12304 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012305 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012306 return;
12307 }
12308 final long origId = Binder.clearCallingIdentity();
12309 finishInstrumentationLocked(app, resultCode, results);
12310 Binder.restoreCallingIdentity(origId);
12311 }
12312 }
12313
12314 // =========================================================
12315 // CONFIGURATION
12316 // =========================================================
12317
12318 public ConfigurationInfo getDeviceConfigurationInfo() {
12319 ConfigurationInfo config = new ConfigurationInfo();
12320 synchronized (this) {
12321 config.reqTouchScreen = mConfiguration.touchscreen;
12322 config.reqKeyboardType = mConfiguration.keyboard;
12323 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012324 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12325 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012326 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12327 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012328 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12329 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012330 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12331 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012332 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012333 }
12334 return config;
12335 }
12336
12337 public Configuration getConfiguration() {
12338 Configuration ci;
12339 synchronized(this) {
12340 ci = new Configuration(mConfiguration);
12341 }
12342 return ci;
12343 }
12344
12345 public void updateConfiguration(Configuration values) {
12346 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12347 "updateConfiguration()");
12348
12349 synchronized(this) {
12350 if (values == null && mWindowManager != null) {
12351 // sentinel: fetch the current configuration from the window manager
12352 values = mWindowManager.computeNewConfiguration();
12353 }
12354
12355 final long origId = Binder.clearCallingIdentity();
12356 updateConfigurationLocked(values, null);
12357 Binder.restoreCallingIdentity(origId);
12358 }
12359 }
12360
12361 /**
12362 * Do either or both things: (1) change the current configuration, and (2)
12363 * make sure the given activity is running with the (now) current
12364 * configuration. Returns true if the activity has been left running, or
12365 * false if <var>starting</var> is being destroyed to match the new
12366 * configuration.
12367 */
12368 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012369 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012370 int changes = 0;
12371
12372 boolean kept = true;
12373
12374 if (values != null) {
12375 Configuration newConfig = new Configuration(mConfiguration);
12376 changes = newConfig.updateFrom(values);
12377 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012378 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012379 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012380 }
12381
Doug Zongker2bec3d42009-12-04 12:52:44 -080012382 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012383
12384 if (values.locale != null) {
12385 saveLocaleLocked(values.locale,
12386 !values.locale.equals(mConfiguration.locale),
12387 values.userSetLocale);
12388 }
12389
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012390 mConfigurationSeq++;
12391 if (mConfigurationSeq <= 0) {
12392 mConfigurationSeq = 1;
12393 }
12394 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012395 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012396 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012397
12398 AttributeCache ac = AttributeCache.instance();
12399 if (ac != null) {
12400 ac.updateConfiguration(mConfiguration);
12401 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012402
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012403 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
12404 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12405 msg.obj = new Configuration(mConfiguration);
12406 mHandler.sendMessage(msg);
12407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012408
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012409 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12410 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012411 try {
12412 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012413 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012414 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012415 app.thread.scheduleConfigurationChanged(mConfiguration);
12416 }
12417 } catch (Exception e) {
12418 }
12419 }
12420 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012421 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12422 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012423 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12424 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012425 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12426 broadcastIntentLocked(null, null,
12427 new Intent(Intent.ACTION_LOCALE_CHANGED),
12428 null, null, 0, null, null,
12429 null, false, false, MY_PID, Process.SYSTEM_UID);
12430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012431 }
12432 }
12433
12434 if (changes != 0 && starting == null) {
12435 // If the configuration changed, and the caller is not already
12436 // in the process of starting an activity, then find the top
12437 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012438 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012439 }
12440
12441 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012442 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012443 // And we need to make sure at this point that all other activities
12444 // are made visible with the correct configuration.
12445 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012446 }
12447
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012448 if (values != null && mWindowManager != null) {
12449 mWindowManager.setNewConfiguration(mConfiguration);
12450 }
12451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012452 return kept;
12453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012454
12455 /**
12456 * Save the locale. You must be inside a synchronized (this) block.
12457 */
12458 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12459 if(isDiff) {
12460 SystemProperties.set("user.language", l.getLanguage());
12461 SystemProperties.set("user.region", l.getCountry());
12462 }
12463
12464 if(isPersist) {
12465 SystemProperties.set("persist.sys.language", l.getLanguage());
12466 SystemProperties.set("persist.sys.country", l.getCountry());
12467 SystemProperties.set("persist.sys.localevar", l.getVariant());
12468 }
12469 }
12470
12471 // =========================================================
12472 // LIFETIME MANAGEMENT
12473 // =========================================================
12474
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012475 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12476 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012477 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012478 // This adjustment has already been computed. If we are calling
12479 // from the top, we may have already computed our adjustment with
12480 // an earlier hidden adjustment that isn't really for us... if
12481 // so, use the new hidden adjustment.
12482 if (!recursed && app.hidden) {
12483 app.curAdj = hiddenAdj;
12484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012485 return app.curAdj;
12486 }
12487
12488 if (app.thread == null) {
12489 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012490 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012491 return (app.curAdj=EMPTY_APP_ADJ);
12492 }
12493
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012494 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12495 // The max adjustment doesn't allow this app to be anything
12496 // below foreground, so it is not worth doing work for it.
12497 app.adjType = "fixed";
12498 app.adjSeq = mAdjSeq;
12499 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012500 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012501 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12502 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012503 }
12504
12505 final boolean hadForegroundActivities = app.foregroundActivities;
12506
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012507 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012508 app.adjSource = null;
12509 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012510 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012511 app.empty = false;
12512 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012513 app.foregroundActivities = false;
12514
12515 final int activitiesSize = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012516
The Android Open Source Project4df24232009-03-05 14:34:35 -080012517 // Determine the importance of the process, starting with most
12518 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012519 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012520 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012521 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012522 // The last app on the list is the foreground app.
12523 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012524 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012525 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012526 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012527 } else if (app.instrumentationClass != null) {
12528 // Don't want to kill running instrumentation.
12529 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012530 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012531 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012532 } else if (app.curReceiver != null ||
12533 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12534 // An app that is currently receiving a broadcast also
12535 // counts as being in the foreground.
12536 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012537 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012538 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012539 } else if (app.executingServices.size() > 0) {
12540 // An app that is currently executing a service callback also
12541 // counts as being in the foreground.
12542 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012543 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012544 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012545 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012546 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012547 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012548 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012549 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012550 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012551 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012552 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012553 // A very not-needed process. If this is lower in the lru list,
12554 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012555 adj = hiddenAdj;
12556 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012557 app.hidden = true;
12558 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012559 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012560 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012561
12562 // Examine all activities if not already foreground.
12563 if (!app.foregroundActivities && activitiesSize > 0) {
12564 for (int j = 0; j < activitiesSize; j++) {
12565 final ActivityRecord r = app.activities.get(j);
12566 if (r.visible) {
12567 // App has a visible activity; only upgrade adjustment.
12568 if (adj > VISIBLE_APP_ADJ) {
12569 adj = VISIBLE_APP_ADJ;
12570 app.adjType = "visible";
12571 }
12572 schedGroup = Process.THREAD_GROUP_DEFAULT;
12573 app.hidden = false;
12574 app.foregroundActivities = true;
12575 break;
12576 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
12577 || r.state == ActivityState.STOPPING) {
12578 // Only upgrade adjustment.
12579 if (adj > PERCEPTIBLE_APP_ADJ) {
12580 adj = PERCEPTIBLE_APP_ADJ;
12581 app.adjType = "stopping";
12582 }
12583 app.foregroundActivities = true;
12584 }
12585 }
12586 }
12587
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012588 if (adj > PERCEPTIBLE_APP_ADJ) {
12589 if (app.foregroundServices) {
12590 // The user is aware of this app, so make it visible.
12591 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012592 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012593 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012594 } else if (app.forcingToForeground != null) {
12595 // The user is aware of this app, so make it visible.
12596 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012597 app.adjType = "force-foreground";
12598 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012599 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012600 }
12601 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012602
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012603 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12604 // We don't want to kill the current heavy-weight process.
12605 adj = HEAVY_WEIGHT_APP_ADJ;
12606 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12607 app.adjType = "heavy";
12608 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012609
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012610 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12611 // This process is hosting what we currently consider to be the
12612 // home app, so we don't want to let it go into the background.
12613 adj = HOME_APP_ADJ;
12614 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12615 app.adjType = "home";
12616 }
12617
Joe Onorato8a9b2202010-02-26 18:56:32 -080012618 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012619
The Android Open Source Project4df24232009-03-05 14:34:35 -080012620 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012621 // there are applications dependent on our services or providers, but
12622 // this gives us a baseline and makes sure we don't get into an
12623 // infinite recursion.
12624 app.adjSeq = mAdjSeq;
12625 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012626
Christopher Tate6fa95972009-06-05 18:43:55 -070012627 if (mBackupTarget != null && app == mBackupTarget.app) {
12628 // If possible we want to avoid killing apps while they're being backed up
12629 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012630 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012631 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012632 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012633 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012634 }
12635 }
12636
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012637 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12638 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012639 final long now = SystemClock.uptimeMillis();
12640 // This process is more important if the top activity is
12641 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012642 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012643 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012644 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012645 if (s.startRequested) {
12646 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12647 // This service has seen some activity within
12648 // recent memory, so we will keep its process ahead
12649 // of the background processes.
12650 if (adj > SECONDARY_SERVER_ADJ) {
12651 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012652 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012653 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012654 }
12655 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012656 // If we have let the service slide into the background
12657 // state, still have some text describing what it is doing
12658 // even though the service no longer has an impact.
12659 if (adj > SECONDARY_SERVER_ADJ) {
12660 app.adjType = "started-bg-services";
12661 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012662 // Don't kill this process because it is doing work; it
12663 // has said it is doing work.
12664 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012665 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012666 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12667 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012668 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012669 = s.connections.values().iterator();
12670 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012671 ArrayList<ConnectionRecord> clist = kt.next();
12672 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12673 // XXX should compute this based on the max of
12674 // all connected clients.
12675 ConnectionRecord cr = clist.get(i);
12676 if (cr.binding.client == app) {
12677 // Binding to ourself is not interesting.
12678 continue;
12679 }
12680 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12681 ProcessRecord client = cr.binding.client;
12682 int myHiddenAdj = hiddenAdj;
12683 if (myHiddenAdj > client.hiddenAdj) {
12684 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12685 myHiddenAdj = client.hiddenAdj;
12686 } else {
12687 myHiddenAdj = VISIBLE_APP_ADJ;
12688 }
12689 }
12690 int clientAdj = computeOomAdjLocked(
12691 client, myHiddenAdj, TOP_APP, true);
12692 if (adj > clientAdj) {
12693 adj = clientAdj >= VISIBLE_APP_ADJ
12694 ? clientAdj : VISIBLE_APP_ADJ;
12695 if (!client.hidden) {
12696 app.hidden = false;
12697 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012698 if (client.keeping) {
12699 app.keeping = true;
12700 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012701 app.adjType = "service";
12702 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12703 .REASON_SERVICE_IN_USE;
12704 app.adjSource = cr.binding.client;
12705 app.adjTarget = s.name;
12706 }
12707 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12708 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12709 schedGroup = Process.THREAD_GROUP_DEFAULT;
12710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012711 }
12712 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012713 ActivityRecord a = cr.activity;
12714 //if (a != null) {
12715 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12716 //}
12717 if (a != null && adj > FOREGROUND_APP_ADJ &&
12718 (a.state == ActivityState.RESUMED
12719 || a.state == ActivityState.PAUSING)) {
12720 adj = FOREGROUND_APP_ADJ;
12721 schedGroup = Process.THREAD_GROUP_DEFAULT;
12722 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012723 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012724 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12725 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012726 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012727 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012729 }
12730 }
12731 }
12732 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012733
Dianne Hackborn287952c2010-09-22 22:34:31 -070012734 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012735 // would like to avoid killing it unless it would prevent the current
12736 // application from running. By default we put the process in
12737 // with the rest of the background processes; as we scan through
12738 // its services we may bump it up from there.
12739 if (adj > hiddenAdj) {
12740 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012741 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012742 app.adjType = "bg-services";
12743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012744 }
12745
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012746 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12747 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012748 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012749 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12750 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012751 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012752 if (cpr.clients.size() != 0) {
12753 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12754 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12755 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012756 if (client == app) {
12757 // Being our own client is not interesting.
12758 continue;
12759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012760 int myHiddenAdj = hiddenAdj;
12761 if (myHiddenAdj > client.hiddenAdj) {
12762 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12763 myHiddenAdj = client.hiddenAdj;
12764 } else {
12765 myHiddenAdj = FOREGROUND_APP_ADJ;
12766 }
12767 }
12768 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012769 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012770 if (adj > clientAdj) {
12771 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012772 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012773 if (!client.hidden) {
12774 app.hidden = false;
12775 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012776 if (client.keeping) {
12777 app.keeping = true;
12778 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012779 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012780 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12781 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012782 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012783 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012784 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012785 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12786 schedGroup = Process.THREAD_GROUP_DEFAULT;
12787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012788 }
12789 }
12790 // If the provider has external (non-framework) process
12791 // dependencies, ensure that its adjustment is at least
12792 // FOREGROUND_APP_ADJ.
12793 if (cpr.externals != 0) {
12794 if (adj > FOREGROUND_APP_ADJ) {
12795 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012796 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012797 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012798 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012799 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012800 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012801 }
12802 }
12803 }
12804 }
12805
12806 app.curRawAdj = adj;
12807
Joe Onorato8a9b2202010-02-26 18:56:32 -080012808 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012809 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12810 if (adj > app.maxAdj) {
12811 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012812 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012813 schedGroup = Process.THREAD_GROUP_DEFAULT;
12814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012815 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012816 if (adj < HIDDEN_APP_MIN_ADJ) {
12817 app.keeping = true;
12818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012819
12820 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012821 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012822
12823 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkeya4620792011-05-20 15:29:23 -070012824 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED,
12825 app.foregroundActivities ? 1 : 0, 0, app).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012826 }
12827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012828 return adj;
12829 }
12830
12831 /**
12832 * Ask a given process to GC right now.
12833 */
12834 final void performAppGcLocked(ProcessRecord app) {
12835 try {
12836 app.lastRequestedGc = SystemClock.uptimeMillis();
12837 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012838 if (app.reportLowMemory) {
12839 app.reportLowMemory = false;
12840 app.thread.scheduleLowMemory();
12841 } else {
12842 app.thread.processInBackground();
12843 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012844 }
12845 } catch (Exception e) {
12846 // whatever.
12847 }
12848 }
12849
12850 /**
12851 * Returns true if things are idle enough to perform GCs.
12852 */
Josh Bartel7f208742010-02-25 11:01:44 -060012853 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012854 return mParallelBroadcasts.size() == 0
12855 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012856 && (mSleeping || (mMainStack.mResumedActivity != null &&
12857 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012858 }
12859
12860 /**
12861 * Perform GCs on all processes that are waiting for it, but only
12862 * if things are idle.
12863 */
12864 final void performAppGcsLocked() {
12865 final int N = mProcessesToGc.size();
12866 if (N <= 0) {
12867 return;
12868 }
Josh Bartel7f208742010-02-25 11:01:44 -060012869 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012870 while (mProcessesToGc.size() > 0) {
12871 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012872 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012873 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12874 <= SystemClock.uptimeMillis()) {
12875 // To avoid spamming the system, we will GC processes one
12876 // at a time, waiting a few seconds between each.
12877 performAppGcLocked(proc);
12878 scheduleAppGcsLocked();
12879 return;
12880 } else {
12881 // It hasn't been long enough since we last GCed this
12882 // process... put it in the list to wait for its time.
12883 addProcessToGcListLocked(proc);
12884 break;
12885 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012886 }
12887 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012888
12889 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012890 }
12891 }
12892
12893 /**
12894 * If all looks good, perform GCs on all processes waiting for them.
12895 */
12896 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012897 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012898 performAppGcsLocked();
12899 return;
12900 }
12901 // Still not idle, wait some more.
12902 scheduleAppGcsLocked();
12903 }
12904
12905 /**
12906 * Schedule the execution of all pending app GCs.
12907 */
12908 final void scheduleAppGcsLocked() {
12909 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012910
12911 if (mProcessesToGc.size() > 0) {
12912 // Schedule a GC for the time to the next process.
12913 ProcessRecord proc = mProcessesToGc.get(0);
12914 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12915
12916 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12917 long now = SystemClock.uptimeMillis();
12918 if (when < (now+GC_TIMEOUT)) {
12919 when = now + GC_TIMEOUT;
12920 }
12921 mHandler.sendMessageAtTime(msg, when);
12922 }
12923 }
12924
12925 /**
12926 * Add a process to the array of processes waiting to be GCed. Keeps the
12927 * list in sorted order by the last GC time. The process can't already be
12928 * on the list.
12929 */
12930 final void addProcessToGcListLocked(ProcessRecord proc) {
12931 boolean added = false;
12932 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12933 if (mProcessesToGc.get(i).lastRequestedGc <
12934 proc.lastRequestedGc) {
12935 added = true;
12936 mProcessesToGc.add(i+1, proc);
12937 break;
12938 }
12939 }
12940 if (!added) {
12941 mProcessesToGc.add(0, proc);
12942 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012943 }
12944
12945 /**
12946 * Set up to ask a process to GC itself. This will either do it
12947 * immediately, or put it on the list of processes to gc the next
12948 * time things are idle.
12949 */
12950 final void scheduleAppGcLocked(ProcessRecord app) {
12951 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012952 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012953 return;
12954 }
12955 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012956 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012957 scheduleAppGcsLocked();
12958 }
12959 }
12960
Dianne Hackborn287952c2010-09-22 22:34:31 -070012961 final void checkExcessivePowerUsageLocked(boolean doKills) {
12962 updateCpuStatsNow();
12963
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012964 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012965 boolean doWakeKills = doKills;
12966 boolean doCpuKills = doKills;
12967 if (mLastPowerCheckRealtime == 0) {
12968 doWakeKills = false;
12969 }
12970 if (mLastPowerCheckUptime == 0) {
12971 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012972 }
12973 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012974 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012975 }
12976 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012977 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12978 final long curUptime = SystemClock.uptimeMillis();
12979 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12980 mLastPowerCheckRealtime = curRealtime;
12981 mLastPowerCheckUptime = curUptime;
12982 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12983 doWakeKills = false;
12984 }
12985 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12986 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012987 }
12988 int i = mLruProcesses.size();
12989 while (i > 0) {
12990 i--;
12991 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012992 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012993 long wtime;
12994 synchronized (stats) {
12995 wtime = stats.getProcessWakeTime(app.info.uid,
12996 app.pid, curRealtime);
12997 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012998 long wtimeUsed = wtime - app.lastWakeTime;
12999 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
13000 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013001 StringBuilder sb = new StringBuilder(128);
13002 sb.append("Wake for ");
13003 app.toShortString(sb);
13004 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013005 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013006 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013007 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013008 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013009 sb.append((wtimeUsed*100)/realtimeSince);
13010 sb.append("%)");
13011 Slog.i(TAG, sb.toString());
13012 sb.setLength(0);
13013 sb.append("CPU for ");
13014 app.toShortString(sb);
13015 sb.append(": over ");
13016 TimeUtils.formatDuration(uptimeSince, sb);
13017 sb.append(" used ");
13018 TimeUtils.formatDuration(cputimeUsed, sb);
13019 sb.append(" (");
13020 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013021 sb.append("%)");
13022 Slog.i(TAG, sb.toString());
13023 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013024 // If a process has held a wake lock for more
13025 // than 50% of the time during this period,
13026 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070013027 if (doWakeKills && realtimeSince > 0
13028 && ((wtimeUsed*100)/realtimeSince) >= 50) {
13029 synchronized (stats) {
13030 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
13031 realtimeSince, wtimeUsed);
13032 }
13033 Slog.w(TAG, "Excessive wake lock in " + app.processName
13034 + " (pid " + app.pid + "): held " + wtimeUsed
13035 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013036 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13037 app.processName, app.setAdj, "excessive wake lock");
13038 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013039 } else if (doCpuKills && uptimeSince > 0
13040 && ((cputimeUsed*100)/uptimeSince) >= 50) {
13041 synchronized (stats) {
13042 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
13043 uptimeSince, cputimeUsed);
13044 }
13045 Slog.w(TAG, "Excessive CPU in " + app.processName
13046 + " (pid " + app.pid + "): used " + cputimeUsed
13047 + " during " + uptimeSince);
13048 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13049 app.processName, app.setAdj, "excessive cpu");
13050 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013051 } else {
13052 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013053 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013054 }
13055 }
13056 }
13057 }
13058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013059 private final boolean updateOomAdjLocked(
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013060 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013061 app.hiddenAdj = hiddenAdj;
13062
13063 if (app.thread == null) {
13064 return true;
13065 }
13066
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013067 boolean success = true;
13068
Dianne Hackborn287952c2010-09-22 22:34:31 -070013069 final boolean wasKeeping = app.keeping;
13070
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013071 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013072
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013073 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013074 if (app.curRawAdj != app.setRawAdj) {
13075 if (app.curRawAdj > FOREGROUND_APP_ADJ
13076 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13077 // If this app is transitioning from foreground to
13078 // non-foreground, have it do a gc.
13079 scheduleAppGcLocked(app);
13080 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13081 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13082 // Likewise do a gc when an app is moving in to the
13083 // background (such as a service stopping).
13084 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013085 }
13086
13087 if (wasKeeping && !app.keeping) {
13088 // This app is no longer something we want to keep. Note
13089 // its current wake lock time to later know to kill it if
13090 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013091 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
13092 synchronized (stats) {
13093 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
13094 app.pid, SystemClock.elapsedRealtime());
13095 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013096 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013097 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013099 app.setRawAdj = app.curRawAdj;
13100 }
13101 if (adj != app.setAdj) {
13102 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013103 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013104 TAG, "Set app " + app.processName +
13105 " oom adj to " + adj);
13106 app.setAdj = adj;
13107 } else {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013108 success = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013109 }
13110 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013111 if (app.setSchedGroup != app.curSchedGroup) {
13112 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013113 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013114 "Setting process group of " + app.processName
13115 + " to " + app.curSchedGroup);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013116 if (app.waitingToKill != null &&
13117 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
13118 Slog.i(TAG, "Killing " + app + ": " + app.waitingToKill);
13119 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13120 app.processName, app.setAdj, app.waitingToKill);
13121 Process.killProcessQuiet(app.pid);
13122 } else {
13123 if (true) {
13124 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013125 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013126 Process.setProcessGroup(app.pid, app.curSchedGroup);
13127 } catch (Exception e) {
13128 Slog.w(TAG, "Failed setting process group of " + app.pid
13129 + " to " + app.curSchedGroup);
13130 e.printStackTrace();
13131 } finally {
13132 Binder.restoreCallingIdentity(oldId);
13133 }
13134 }
13135 if (false) {
13136 if (app.thread != null) {
13137 try {
13138 app.thread.setSchedulingGroup(app.curSchedGroup);
13139 } catch (RemoteException e) {
13140 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013141 }
13142 }
13143 }
13144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013145 }
13146
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013147 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013148 }
13149
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013150 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013151 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013152 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013153 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013154 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013155 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013156 }
13157 }
13158 return resumedActivity;
13159 }
13160
13161 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013162 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013163 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13164 int curAdj = app.curAdj;
13165 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13166 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13167
13168 mAdjSeq++;
13169
13170 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13171 if (res) {
13172 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13173 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13174 if (nowHidden != wasHidden) {
13175 // Changed to/from hidden state, so apps after it in the LRU
13176 // list may also be changed.
13177 updateOomAdjLocked();
13178 }
13179 }
13180 return res;
13181 }
13182
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013183 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013184 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013185 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013186 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13187
13188 if (false) {
13189 RuntimeException e = new RuntimeException();
13190 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013191 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013192 }
13193
13194 mAdjSeq++;
13195
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013196 // Let's determine how many processes we have running vs.
13197 // how many slots we have for background processes; we may want
13198 // to put multiple processes in a slot of there are enough of
13199 // them.
13200 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13201 int factor = (mLruProcesses.size()-4)/numSlots;
13202 if (factor < 1) factor = 1;
13203 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013204 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013206 // First try updating the OOM adjustment for each of the
13207 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013208 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013209 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
13210 while (i > 0) {
13211 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013212 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013213 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013214 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013215 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013216 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013217 step++;
13218 if (step >= factor) {
13219 step = 0;
13220 curHiddenAdj++;
13221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013222 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013223 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070013224 if (!app.killedBackground) {
13225 numHidden++;
13226 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070013227 Slog.i(TAG, "No longer want " + app.processName
13228 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013229 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13230 app.processName, app.setAdj, "too many background");
13231 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070013232 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013233 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013234 }
13235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013236 } else {
13237 didOomAdj = false;
13238 }
13239 }
13240
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013241 // If we return false, we will fall back on killing processes to
13242 // have a fixed limit. Do this if a limit has been requested; else
13243 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013244 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13245 }
13246
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013247 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013248 synchronized (this) {
13249 int i;
13250
13251 // First remove any unused application processes whose package
13252 // has been removed.
13253 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13254 final ProcessRecord app = mRemovedProcesses.get(i);
13255 if (app.activities.size() == 0
13256 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013257 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013258 TAG, "Exiting empty application process "
13259 + app.processName + " ("
13260 + (app.thread != null ? app.thread.asBinder() : null)
13261 + ")\n");
13262 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013263 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13264 app.processName, app.setAdj, "empty");
13265 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013266 } else {
13267 try {
13268 app.thread.scheduleExit();
13269 } catch (Exception e) {
13270 // Ignore exceptions.
13271 }
13272 }
13273 cleanUpApplicationRecordLocked(app, false, -1);
13274 mRemovedProcesses.remove(i);
13275
13276 if (app.persistent) {
13277 if (app.persistent) {
13278 addAppLocked(app.info);
13279 }
13280 }
13281 }
13282 }
13283
13284 // Now try updating the OOM adjustment for each of the
13285 // application processes based on their current state.
13286 // If the setOomAdj() API is not supported, then go with our
13287 // back-up plan...
13288 if (!updateOomAdjLocked()) {
13289
13290 // Count how many processes are running services.
13291 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013292 for (i=mLruProcesses.size()-1; i>=0; i--) {
13293 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013294
13295 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013296 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013297 // Don't count processes holding services against our
13298 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013299 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013300 TAG, "Not trimming app " + app + " with services: "
13301 + app.services);
13302 numServiceProcs++;
13303 }
13304 }
13305
13306 int curMaxProcs = mProcessLimit;
13307 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13308 if (mAlwaysFinishActivities) {
13309 curMaxProcs = 1;
13310 }
13311 curMaxProcs += numServiceProcs;
13312
13313 // Quit as many processes as we can to get down to the desired
13314 // process count. First remove any processes that no longer
13315 // have activites running in them.
13316 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013317 i<mLruProcesses.size()
13318 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013319 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013320 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013321 // Quit an application only if it is not currently
13322 // running any activities.
13323 if (!app.persistent && app.activities.size() == 0
13324 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013325 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013326 TAG, "Exiting empty application process "
13327 + app.processName + " ("
13328 + (app.thread != null ? app.thread.asBinder() : null)
13329 + ")\n");
13330 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013331 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13332 app.processName, app.setAdj, "empty");
13333 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013334 } else {
13335 try {
13336 app.thread.scheduleExit();
13337 } catch (Exception e) {
13338 // Ignore exceptions.
13339 }
13340 }
13341 // todo: For now we assume the application is not buggy
13342 // or evil, and will quit as a result of our request.
13343 // Eventually we need to drive this off of the death
13344 // notification, and kill the process if it takes too long.
13345 cleanUpApplicationRecordLocked(app, false, i);
13346 i--;
13347 }
13348 }
13349
13350 // If we still have too many processes, now from the least
13351 // recently used process we start finishing activities.
Joe Onorato43a17652011-04-06 19:22:23 -070013352 if (false) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013353 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013354 " of " + curMaxProcs + " processes");
13355 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013356 i<mLruProcesses.size()
13357 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013358 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013359 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013360 // Quit the application only if we have a state saved for
13361 // all of its activities.
13362 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013363 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013364 int NUMA = app.activities.size();
13365 int j;
Joe Onorato43a17652011-04-06 19:22:23 -070013366 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013367 TAG, "Looking to quit " + app.processName);
13368 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013369 ActivityRecord r = app.activities.get(j);
Joe Onorato43a17652011-04-06 19:22:23 -070013370 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013371 TAG, " " + r.intent.getComponent().flattenToShortString()
13372 + ": frozen=" + r.haveState + ", visible=" + r.visible);
13373 canQuit = (r.haveState || !r.stateNotNeeded)
13374 && !r.visible && r.stopped;
13375 }
13376 if (canQuit) {
13377 // Finish all of the activities, and then the app itself.
13378 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013379 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013380 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013381 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013382 }
13383 r.resultTo = null;
13384 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013385 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013386 + app.processName + " ("
13387 + (app.thread != null ? app.thread.asBinder() : null)
13388 + ")\n");
13389 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013390 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13391 app.processName, app.setAdj, "old background");
13392 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013393 } else {
13394 try {
13395 app.thread.scheduleExit();
13396 } catch (Exception e) {
13397 // Ignore exceptions.
13398 }
13399 }
13400 // todo: For now we assume the application is not buggy
13401 // or evil, and will quit as a result of our request.
13402 // Eventually we need to drive this off of the death
13403 // notification, and kill the process if it takes too long.
13404 cleanUpApplicationRecordLocked(app, false, i);
13405 i--;
13406 //dump();
13407 }
13408 }
13409
13410 }
13411
13412 int curMaxActivities = MAX_ACTIVITIES;
13413 if (mAlwaysFinishActivities) {
13414 curMaxActivities = 1;
13415 }
13416
13417 // Finally, if there are too many activities now running, try to
13418 // finish as many as we can to get back down to the limit.
13419 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013420 i<mMainStack.mLRUActivities.size()
13421 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013422 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013423 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013424 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013425
13426 // We can finish this one if we have its icicle saved and
13427 // it is not persistent.
13428 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013429 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013430 final int origSize = mMainStack.mLRUActivities.size();
13431 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013432
13433 // This will remove it from the LRU list, so keep
13434 // our index at the same value. Note that this check to
13435 // see if the size changes is just paranoia -- if
13436 // something unexpected happens, we don't want to end up
13437 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013438 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013439 i--;
13440 }
13441 }
13442 }
13443 }
13444 }
13445
13446 /** This method sends the specified signal to each of the persistent apps */
13447 public void signalPersistentProcesses(int sig) throws RemoteException {
13448 if (sig != Process.SIGNAL_USR1) {
13449 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13450 }
13451
13452 synchronized (this) {
13453 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13454 != PackageManager.PERMISSION_GRANTED) {
13455 throw new SecurityException("Requires permission "
13456 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13457 }
13458
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013459 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13460 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013461 if (r.thread != null && r.persistent) {
13462 Process.sendSignal(r.pid, sig);
13463 }
13464 }
13465 }
13466 }
13467
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013468 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013469 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013470
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013471 try {
13472 synchronized (this) {
13473 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13474 // its own permission.
13475 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13476 != PackageManager.PERMISSION_GRANTED) {
13477 throw new SecurityException("Requires permission "
13478 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013479 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013480
13481 if (start && fd == null) {
13482 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013483 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013484
13485 ProcessRecord proc = null;
13486 try {
13487 int pid = Integer.parseInt(process);
13488 synchronized (mPidsSelfLocked) {
13489 proc = mPidsSelfLocked.get(pid);
13490 }
13491 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013492 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013493
13494 if (proc == null) {
13495 HashMap<String, SparseArray<ProcessRecord>> all
13496 = mProcessNames.getMap();
13497 SparseArray<ProcessRecord> procs = all.get(process);
13498 if (procs != null && procs.size() > 0) {
13499 proc = procs.valueAt(0);
13500 }
13501 }
13502
13503 if (proc == null || proc.thread == null) {
13504 throw new IllegalArgumentException("Unknown process: " + process);
13505 }
13506
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013507 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13508 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013509 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13510 throw new SecurityException("Process not debuggable: " + proc);
13511 }
13512 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013513
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013514 proc.thread.profilerControl(start, path, fd);
13515 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013516 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013517 }
13518 } catch (RemoteException e) {
13519 throw new IllegalStateException("Process disappeared");
13520 } finally {
13521 if (fd != null) {
13522 try {
13523 fd.close();
13524 } catch (IOException e) {
13525 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013526 }
13527 }
13528 }
Andy McFadden824c5102010-07-09 16:26:57 -070013529
13530 public boolean dumpHeap(String process, boolean managed,
13531 String path, ParcelFileDescriptor fd) throws RemoteException {
13532
13533 try {
13534 synchronized (this) {
13535 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13536 // its own permission (same as profileControl).
13537 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13538 != PackageManager.PERMISSION_GRANTED) {
13539 throw new SecurityException("Requires permission "
13540 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13541 }
13542
13543 if (fd == null) {
13544 throw new IllegalArgumentException("null fd");
13545 }
13546
13547 ProcessRecord proc = null;
13548 try {
13549 int pid = Integer.parseInt(process);
13550 synchronized (mPidsSelfLocked) {
13551 proc = mPidsSelfLocked.get(pid);
13552 }
13553 } catch (NumberFormatException e) {
13554 }
13555
13556 if (proc == null) {
13557 HashMap<String, SparseArray<ProcessRecord>> all
13558 = mProcessNames.getMap();
13559 SparseArray<ProcessRecord> procs = all.get(process);
13560 if (procs != null && procs.size() > 0) {
13561 proc = procs.valueAt(0);
13562 }
13563 }
13564
13565 if (proc == null || proc.thread == null) {
13566 throw new IllegalArgumentException("Unknown process: " + process);
13567 }
13568
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013569 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13570 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013571 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13572 throw new SecurityException("Process not debuggable: " + proc);
13573 }
13574 }
13575
13576 proc.thread.dumpHeap(managed, path, fd);
13577 fd = null;
13578 return true;
13579 }
13580 } catch (RemoteException e) {
13581 throw new IllegalStateException("Process disappeared");
13582 } finally {
13583 if (fd != null) {
13584 try {
13585 fd.close();
13586 } catch (IOException e) {
13587 }
13588 }
13589 }
13590 }
13591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013592 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13593 public void monitor() {
13594 synchronized (this) { }
13595 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013596
13597 public void onCoreSettingsChange(Bundle settings) {
13598 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13599 ProcessRecord processRecord = mLruProcesses.get(i);
13600 try {
13601 if (processRecord.thread != null) {
13602 processRecord.thread.setCoreSettings(settings);
13603 }
13604 } catch (RemoteException re) {
13605 /* ignore */
13606 }
13607 }
13608 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070013609
13610 // Multi-user methods
13611
13612 public boolean switchUser(int userid) {
13613 // TODO
13614 return true;
13615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013616}