blob: 262e5cee9d2747f98886355d956db4b04c52dd05 [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)
3679 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3680 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003681
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003682 ensurePackageDexOpt(app.instrumentationInfo != null
3683 ? app.instrumentationInfo.packageName
3684 : app.info.packageName);
3685 if (app.instrumentationClass != null) {
3686 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003687 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003688 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003689 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003690 ApplicationInfo appInfo = app.instrumentationInfo != null
3691 ? app.instrumentationInfo : app.info;
3692 thread.bindApplication(processName, appInfo, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 app.instrumentationClass, app.instrumentationProfileFile,
3694 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003695 isRestrictedBackupMode || !normalMode,
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003696 mConfiguration, compatibilityInfoForPackageLocked(appInfo),
3697 getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003698 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003699 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003700 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 } catch (Exception e) {
3702 // todo: Yikes! What should we do? For now we will try to
3703 // start another process, but that could easily get us in
3704 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003705 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706
3707 app.resetPackageList();
3708 startProcessLocked(app, "bind fail", processName);
3709 return false;
3710 }
3711
3712 // Remove this record from the list of starting applications.
3713 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003714 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3715 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003716 mProcessesOnHold.remove(app);
3717
3718 boolean badApp = false;
3719 boolean didSomething = false;
3720
3721 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003722 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003723 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003724 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3725 && processName.equals(hr.processName)) {
3726 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003727 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003728 didSomething = true;
3729 }
3730 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003731 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003732 + hr.intent.getComponent().flattenToShortString(), e);
3733 badApp = true;
3734 }
3735 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003736 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 }
3738 }
3739
3740 // Find any services that should be running in this process...
3741 if (!badApp && mPendingServices.size() > 0) {
3742 ServiceRecord sr = null;
3743 try {
3744 for (int i=0; i<mPendingServices.size(); i++) {
3745 sr = mPendingServices.get(i);
3746 if (app.info.uid != sr.appInfo.uid
3747 || !processName.equals(sr.processName)) {
3748 continue;
3749 }
3750
3751 mPendingServices.remove(i);
3752 i--;
3753 realStartServiceLocked(sr, app);
3754 didSomething = true;
3755 }
3756 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003757 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003758 + sr.shortName, e);
3759 badApp = true;
3760 }
3761 }
3762
3763 // Check if the next broadcast receiver is in this process...
3764 BroadcastRecord br = mPendingBroadcast;
3765 if (!badApp && br != null && br.curApp == app) {
3766 try {
3767 mPendingBroadcast = null;
3768 processCurBroadcastLocked(br, app);
3769 didSomething = true;
3770 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003771 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003772 + br.curComponent.flattenToShortString(), e);
3773 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003774 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3776 br.resultExtras, br.resultAbort, true);
3777 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003778 // We need to reset the state if we fails to start the receiver.
3779 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003780 }
3781 }
3782
Christopher Tate181fafa2009-05-14 11:12:14 -07003783 // Check whether the next backup agent is in this process...
3784 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003785 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003786 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003787 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003788 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
3789 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
3790 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07003791 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003792 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003793 e.printStackTrace();
3794 }
3795 }
3796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003797 if (badApp) {
3798 // todo: Also need to kill application to deal with all
3799 // kinds of exceptions.
3800 handleAppDiedLocked(app, false);
3801 return false;
3802 }
3803
3804 if (!didSomething) {
3805 updateOomAdjLocked();
3806 }
3807
3808 return true;
3809 }
3810
3811 public final void attachApplication(IApplicationThread thread) {
3812 synchronized (this) {
3813 int callingPid = Binder.getCallingPid();
3814 final long origId = Binder.clearCallingIdentity();
3815 attachApplicationLocked(thread, callingPid);
3816 Binder.restoreCallingIdentity(origId);
3817 }
3818 }
3819
Dianne Hackborne88846e2009-09-30 21:34:25 -07003820 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003822 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003823 Binder.restoreCallingIdentity(origId);
3824 }
3825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003827 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003828 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003829 mWindowManager.enableScreenAfterBoot();
3830 }
3831
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003832 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003833 IntentFilter pkgFilter = new IntentFilter();
3834 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3835 pkgFilter.addDataScheme("package");
3836 mContext.registerReceiver(new BroadcastReceiver() {
3837 @Override
3838 public void onReceive(Context context, Intent intent) {
3839 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3840 if (pkgs != null) {
3841 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003842 synchronized (ActivityManagerService.this) {
3843 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3844 setResultCode(Activity.RESULT_OK);
3845 return;
3846 }
3847 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003848 }
3849 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003850 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003851 }, pkgFilter);
3852
3853 synchronized (this) {
3854 // Ensure that any processes we had put on hold are now started
3855 // up.
3856 final int NP = mProcessesOnHold.size();
3857 if (NP > 0) {
3858 ArrayList<ProcessRecord> procs =
3859 new ArrayList<ProcessRecord>(mProcessesOnHold);
3860 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003861 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3862 + procs.get(ip));
3863 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003864 }
3865 }
3866
3867 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003868 // Start looking for apps that are abusing wake locks.
3869 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003870 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003871 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003872 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003873 broadcastIntentLocked(null, null,
3874 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3875 null, null, 0, null, null,
3876 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3877 false, false, MY_PID, Process.SYSTEM_UID);
3878 }
3879 }
3880 }
3881
3882 final void ensureBootCompleted() {
3883 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003884 boolean enableScreen;
3885 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003886 booting = mBooting;
3887 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003888 enableScreen = !mBooted;
3889 mBooted = true;
3890 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003891
3892 if (booting) {
3893 finishBooting();
3894 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003895
3896 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003897 enableScreenAfterBoot();
3898 }
3899 }
3900
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003901 public final void activityPaused(IBinder token) {
3902 final long origId = Binder.clearCallingIdentity();
3903 mMainStack.activityPaused(token, false);
3904 Binder.restoreCallingIdentity(origId);
3905 }
3906
3907 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3908 CharSequence description) {
3909 if (localLOGV) Slog.v(
3910 TAG, "Activity stopped: token=" + token);
3911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003912 // Refuse possible leaked file descriptors
3913 if (icicle != null && icicle.hasFileDescriptors()) {
3914 throw new IllegalArgumentException("File descriptors passed in Bundle");
3915 }
3916
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003917 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918
3919 final long origId = Binder.clearCallingIdentity();
3920
3921 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003922 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003923 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003924 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003925 r.icicle = icicle;
3926 r.haveState = true;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003927 r.updateThumbnail(thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 r.stopped = true;
3929 r.state = ActivityState.STOPPED;
3930 if (!r.finishing) {
3931 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003932 r.stack.destroyActivityLocked(r, true);
3933 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 }
3935 }
3936 }
3937 }
3938
3939 if (r != null) {
3940 sendPendingThumbnail(r, null, null, null, false);
3941 }
3942
3943 trimApplications();
3944
3945 Binder.restoreCallingIdentity(origId);
3946 }
3947
3948 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003949 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003950 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 }
3952
3953 public String getCallingPackage(IBinder token) {
3954 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003955 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003956 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003957 }
3958 }
3959
3960 public ComponentName getCallingActivity(IBinder token) {
3961 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003962 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003963 return r != null ? r.intent.getComponent() : null;
3964 }
3965 }
3966
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003967 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003968 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003969 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003970 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003971 if (r != null) {
3972 return r.resultTo;
3973 }
3974 }
3975 return null;
3976 }
3977
3978 public ComponentName getActivityClassForToken(IBinder token) {
3979 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003980 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003981 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003982 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 return r.intent.getComponent();
3984 }
3985 return null;
3986 }
3987 }
3988
3989 public String getPackageForToken(IBinder token) {
3990 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003991 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003992 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003993 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003994 return r.packageName;
3995 }
3996 return null;
3997 }
3998 }
3999
4000 public IIntentSender getIntentSender(int type,
4001 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004002 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004003 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004004 if (intents != null) {
4005 if (intents.length < 1) {
4006 throw new IllegalArgumentException("Intents array length must be >= 1");
4007 }
4008 for (int i=0; i<intents.length; i++) {
4009 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07004010 if (intent != null) {
4011 if (intent.hasFileDescriptors()) {
4012 throw new IllegalArgumentException("File descriptors passed in Intent");
4013 }
4014 if (type == INTENT_SENDER_BROADCAST &&
4015 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
4016 throw new IllegalArgumentException(
4017 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
4018 }
4019 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004020 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004021 }
4022 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004023 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004024 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004025 }
4026 }
4027
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004028 synchronized(this) {
4029 int callingUid = Binder.getCallingUid();
4030 try {
4031 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
4032 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004033 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 .getPackageUid(packageName);
4035 if (uid != Binder.getCallingUid()) {
4036 String msg = "Permission Denial: getIntentSender() from pid="
4037 + Binder.getCallingPid()
4038 + ", uid=" + Binder.getCallingUid()
4039 + ", (need uid=" + uid + ")"
4040 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004041 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004042 throw new SecurityException(msg);
4043 }
4044 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004045
4046 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004047 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004049 } catch (RemoteException e) {
4050 throw new SecurityException(e);
4051 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004052 }
4053 }
4054
4055 IIntentSender getIntentSenderLocked(int type,
4056 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004057 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004058 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004059 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004060 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004061 if (index < 0) {
4062 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004063 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004064 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004065 if (activity.finishing) {
4066 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004067 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004068 }
4069
4070 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4071 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4072 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4073 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4074 |PendingIntent.FLAG_UPDATE_CURRENT);
4075
4076 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4077 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004078 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004079 WeakReference<PendingIntentRecord> ref;
4080 ref = mIntentSenderRecords.get(key);
4081 PendingIntentRecord rec = ref != null ? ref.get() : null;
4082 if (rec != null) {
4083 if (!cancelCurrent) {
4084 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004085 if (rec.key.requestIntent != null) {
4086 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4087 }
4088 if (intents != null) {
4089 intents[intents.length-1] = rec.key.requestIntent;
4090 rec.key.allIntents = intents;
4091 rec.key.allResolvedTypes = resolvedTypes;
4092 } else {
4093 rec.key.allIntents = null;
4094 rec.key.allResolvedTypes = null;
4095 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 return rec;
4098 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004099 rec.canceled = true;
4100 mIntentSenderRecords.remove(key);
4101 }
4102 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004103 return rec;
4104 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004105 rec = new PendingIntentRecord(this, key, callingUid);
4106 mIntentSenderRecords.put(key, rec.ref);
4107 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4108 if (activity.pendingResults == null) {
4109 activity.pendingResults
4110 = new HashSet<WeakReference<PendingIntentRecord>>();
4111 }
4112 activity.pendingResults.add(rec.ref);
4113 }
4114 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004115 }
4116
4117 public void cancelIntentSender(IIntentSender sender) {
4118 if (!(sender instanceof PendingIntentRecord)) {
4119 return;
4120 }
4121 synchronized(this) {
4122 PendingIntentRecord rec = (PendingIntentRecord)sender;
4123 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004124 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125 .getPackageUid(rec.key.packageName);
4126 if (uid != Binder.getCallingUid()) {
4127 String msg = "Permission Denial: cancelIntentSender() from pid="
4128 + Binder.getCallingPid()
4129 + ", uid=" + Binder.getCallingUid()
4130 + " is not allowed to cancel packges "
4131 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004132 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004133 throw new SecurityException(msg);
4134 }
4135 } catch (RemoteException e) {
4136 throw new SecurityException(e);
4137 }
4138 cancelIntentSenderLocked(rec, true);
4139 }
4140 }
4141
4142 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4143 rec.canceled = true;
4144 mIntentSenderRecords.remove(rec.key);
4145 if (cleanActivity && rec.key.activity != null) {
4146 rec.key.activity.pendingResults.remove(rec.ref);
4147 }
4148 }
4149
4150 public String getPackageForIntentSender(IIntentSender pendingResult) {
4151 if (!(pendingResult instanceof PendingIntentRecord)) {
4152 return null;
4153 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004154 try {
4155 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4156 return res.key.packageName;
4157 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 }
4159 return null;
4160 }
4161
4162 public void setProcessLimit(int max) {
4163 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4164 "setProcessLimit()");
4165 mProcessLimit = max;
4166 }
4167
4168 public int getProcessLimit() {
4169 return mProcessLimit;
4170 }
4171
4172 void foregroundTokenDied(ForegroundToken token) {
4173 synchronized (ActivityManagerService.this) {
4174 synchronized (mPidsSelfLocked) {
4175 ForegroundToken cur
4176 = mForegroundProcesses.get(token.pid);
4177 if (cur != token) {
4178 return;
4179 }
4180 mForegroundProcesses.remove(token.pid);
4181 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4182 if (pr == null) {
4183 return;
4184 }
4185 pr.forcingToForeground = null;
4186 pr.foregroundServices = false;
4187 }
4188 updateOomAdjLocked();
4189 }
4190 }
4191
4192 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4193 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4194 "setProcessForeground()");
4195 synchronized(this) {
4196 boolean changed = false;
4197
4198 synchronized (mPidsSelfLocked) {
4199 ProcessRecord pr = mPidsSelfLocked.get(pid);
4200 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004201 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 return;
4203 }
4204 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4205 if (oldToken != null) {
4206 oldToken.token.unlinkToDeath(oldToken, 0);
4207 mForegroundProcesses.remove(pid);
4208 pr.forcingToForeground = null;
4209 changed = true;
4210 }
4211 if (isForeground && token != null) {
4212 ForegroundToken newToken = new ForegroundToken() {
4213 public void binderDied() {
4214 foregroundTokenDied(this);
4215 }
4216 };
4217 newToken.pid = pid;
4218 newToken.token = token;
4219 try {
4220 token.linkToDeath(newToken, 0);
4221 mForegroundProcesses.put(pid, newToken);
4222 pr.forcingToForeground = token;
4223 changed = true;
4224 } catch (RemoteException e) {
4225 // If the process died while doing this, we will later
4226 // do the cleanup with the process death link.
4227 }
4228 }
4229 }
4230
4231 if (changed) {
4232 updateOomAdjLocked();
4233 }
4234 }
4235 }
4236
4237 // =========================================================
4238 // PERMISSIONS
4239 // =========================================================
4240
4241 static class PermissionController extends IPermissionController.Stub {
4242 ActivityManagerService mActivityManagerService;
4243 PermissionController(ActivityManagerService activityManagerService) {
4244 mActivityManagerService = activityManagerService;
4245 }
4246
4247 public boolean checkPermission(String permission, int pid, int uid) {
4248 return mActivityManagerService.checkPermission(permission, pid,
4249 uid) == PackageManager.PERMISSION_GRANTED;
4250 }
4251 }
4252
4253 /**
4254 * This can be called with or without the global lock held.
4255 */
4256 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004257 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004258 // We might be performing an operation on behalf of an indirect binder
4259 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4260 // client identity accordingly before proceeding.
4261 Identity tlsIdentity = sCallerIdentity.get();
4262 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004263 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004264 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4265 uid = tlsIdentity.uid;
4266 pid = tlsIdentity.pid;
4267 }
4268
4269 // Root, system server and our own process get to do everything.
4270 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4271 !Process.supportsProcesses()) {
4272 return PackageManager.PERMISSION_GRANTED;
4273 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004274 // If there is a uid that owns whatever is being accessed, it has
4275 // blanket access to it regardless of the permissions it requires.
4276 if (owningUid >= 0 && uid == owningUid) {
4277 return PackageManager.PERMISSION_GRANTED;
4278 }
4279 // If the target is not exported, then nobody else can get to it.
4280 if (!exported) {
4281 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 return PackageManager.PERMISSION_DENIED;
4283 }
4284 if (permission == null) {
4285 return PackageManager.PERMISSION_GRANTED;
4286 }
4287 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004288 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 .checkUidPermission(permission, uid);
4290 } catch (RemoteException e) {
4291 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004292 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004293 }
4294 return PackageManager.PERMISSION_DENIED;
4295 }
4296
4297 /**
4298 * As the only public entry point for permissions checking, this method
4299 * can enforce the semantic that requesting a check on a null global
4300 * permission is automatically denied. (Internally a null permission
4301 * string is used when calling {@link #checkComponentPermission} in cases
4302 * when only uid-based security is needed.)
4303 *
4304 * This can be called with or without the global lock held.
4305 */
4306 public int checkPermission(String permission, int pid, int uid) {
4307 if (permission == null) {
4308 return PackageManager.PERMISSION_DENIED;
4309 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004310 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 }
4312
4313 /**
4314 * Binder IPC calls go through the public entry point.
4315 * This can be called with or without the global lock held.
4316 */
4317 int checkCallingPermission(String permission) {
4318 return checkPermission(permission,
4319 Binder.getCallingPid(),
4320 Binder.getCallingUid());
4321 }
4322
4323 /**
4324 * This can be called with or without the global lock held.
4325 */
4326 void enforceCallingPermission(String permission, String func) {
4327 if (checkCallingPermission(permission)
4328 == PackageManager.PERMISSION_GRANTED) {
4329 return;
4330 }
4331
4332 String msg = "Permission Denial: " + func + " from pid="
4333 + Binder.getCallingPid()
4334 + ", uid=" + Binder.getCallingUid()
4335 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004336 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004337 throw new SecurityException(msg);
4338 }
4339
4340 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004341 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4342 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4343 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4344 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4345 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004347 // Is the component private from the target uid?
4348 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4349
4350 // Acceptable if the there is no read permission needed from the
4351 // target or the target is holding the read permission.
4352 if (!readPerm) {
4353 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004354 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004355 == PackageManager.PERMISSION_GRANTED)) {
4356 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 }
4358 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004359
4360 // Acceptable if the there is no write permission needed from the
4361 // target or the target is holding the read permission.
4362 if (!writePerm) {
4363 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004364 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004365 == PackageManager.PERMISSION_GRANTED)) {
4366 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367 }
4368 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004369
4370 // Acceptable if there is a path permission matching the URI that
4371 // the target holds the permission on.
4372 PathPermission[] pps = pi.pathPermissions;
4373 if (pps != null && (!readPerm || !writePerm)) {
4374 final String path = uri.getPath();
4375 int i = pps.length;
4376 while (i > 0 && (!readPerm || !writePerm)) {
4377 i--;
4378 PathPermission pp = pps[i];
4379 if (!readPerm) {
4380 final String pprperm = pp.getReadPermission();
4381 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4382 + pprperm + " for " + pp.getPath()
4383 + ": match=" + pp.match(path)
4384 + " check=" + pm.checkUidPermission(pprperm, uid));
4385 if (pprperm != null && pp.match(path) &&
4386 (pm.checkUidPermission(pprperm, uid)
4387 == PackageManager.PERMISSION_GRANTED)) {
4388 readPerm = true;
4389 }
4390 }
4391 if (!writePerm) {
4392 final String ppwperm = pp.getWritePermission();
4393 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4394 + ppwperm + " for " + pp.getPath()
4395 + ": match=" + pp.match(path)
4396 + " check=" + pm.checkUidPermission(ppwperm, uid));
4397 if (ppwperm != null && pp.match(path) &&
4398 (pm.checkUidPermission(ppwperm, uid)
4399 == PackageManager.PERMISSION_GRANTED)) {
4400 writePerm = true;
4401 }
4402 }
4403 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004405 } catch (RemoteException e) {
4406 return false;
4407 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004408
4409 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 }
4411
4412 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4413 int modeFlags) {
4414 // Root gets to do everything.
4415 if (uid == 0 || !Process.supportsProcesses()) {
4416 return true;
4417 }
4418 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4419 if (perms == null) return false;
4420 UriPermission perm = perms.get(uri);
4421 if (perm == null) return false;
4422 return (modeFlags&perm.modeFlags) == modeFlags;
4423 }
4424
4425 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4426 // Another redirected-binder-call permissions check as in
4427 // {@link checkComponentPermission}.
4428 Identity tlsIdentity = sCallerIdentity.get();
4429 if (tlsIdentity != null) {
4430 uid = tlsIdentity.uid;
4431 pid = tlsIdentity.pid;
4432 }
4433
4434 // Our own process gets to do everything.
4435 if (pid == MY_PID) {
4436 return PackageManager.PERMISSION_GRANTED;
4437 }
4438 synchronized(this) {
4439 return checkUriPermissionLocked(uri, uid, modeFlags)
4440 ? PackageManager.PERMISSION_GRANTED
4441 : PackageManager.PERMISSION_DENIED;
4442 }
4443 }
4444
Dianne Hackborn39792d22010-08-19 18:01:52 -07004445 /**
4446 * Check if the targetPkg can be granted permission to access uri by
4447 * the callingUid using the given modeFlags. Throws a security exception
4448 * if callingUid is not allowed to do this. Returns the uid of the target
4449 * if the URI permission grant should be performed; returns -1 if it is not
4450 * needed (for example targetPkg already has permission to access the URI).
4451 */
4452 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4453 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004454 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4455 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4456 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004457 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 }
4459
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004460 if (targetPkg != null) {
4461 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4462 "Checking grant " + targetPkg + " permission to " + uri);
4463 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004464
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004465 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466
4467 // If this is not a content: uri, we can't do anything with it.
4468 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004469 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004470 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004471 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004472 }
4473
4474 String name = uri.getAuthority();
4475 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004476 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004477 if (cpr != null) {
4478 pi = cpr.info;
4479 } else {
4480 try {
4481 pi = pm.resolveContentProvider(name,
4482 PackageManager.GET_URI_PERMISSION_PATTERNS);
4483 } catch (RemoteException ex) {
4484 }
4485 }
4486 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004487 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004488 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 }
4490
4491 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004492 if (targetPkg != null) {
4493 try {
4494 targetUid = pm.getPackageUid(targetPkg);
4495 if (targetUid < 0) {
4496 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4497 "Can't grant URI permission no uid for: " + targetPkg);
4498 return -1;
4499 }
4500 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004501 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004503 } else {
4504 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 }
4506
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004507 if (targetUid >= 0) {
4508 // First... does the target actually need this permission?
4509 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4510 // No need to grant the target this permission.
4511 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4512 "Target " + targetPkg + " already has full permission to " + uri);
4513 return -1;
4514 }
4515 } else {
4516 // First... there is no target package, so can anyone access it?
4517 boolean allowed = pi.exported;
4518 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4519 if (pi.readPermission != null) {
4520 allowed = false;
4521 }
4522 }
4523 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4524 if (pi.writePermission != null) {
4525 allowed = false;
4526 }
4527 }
4528 if (allowed) {
4529 return -1;
4530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004531 }
4532
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004533 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 if (!pi.grantUriPermissions) {
4535 throw new SecurityException("Provider " + pi.packageName
4536 + "/" + pi.name
4537 + " does not allow granting of Uri permissions (uri "
4538 + uri + ")");
4539 }
4540 if (pi.uriPermissionPatterns != null) {
4541 final int N = pi.uriPermissionPatterns.length;
4542 boolean allowed = false;
4543 for (int i=0; i<N; i++) {
4544 if (pi.uriPermissionPatterns[i] != null
4545 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4546 allowed = true;
4547 break;
4548 }
4549 }
4550 if (!allowed) {
4551 throw new SecurityException("Provider " + pi.packageName
4552 + "/" + pi.name
4553 + " does not allow granting of permission to path of Uri "
4554 + uri);
4555 }
4556 }
4557
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004558 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004560 if (callingUid != Process.myUid()) {
4561 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4562 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4563 throw new SecurityException("Uid " + callingUid
4564 + " does not have permission to uri " + uri);
4565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004566 }
4567 }
4568
Dianne Hackborn39792d22010-08-19 18:01:52 -07004569 return targetUid;
4570 }
4571
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004572 public int checkGrantUriPermission(int callingUid, String targetPkg,
4573 Uri uri, int modeFlags) {
4574 synchronized(this) {
4575 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4576 }
4577 }
4578
Dianne Hackborn39792d22010-08-19 18:01:52 -07004579 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4580 Uri uri, int modeFlags, UriPermissionOwner owner) {
4581 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4582 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4583 if (modeFlags == 0) {
4584 return;
4585 }
4586
4587 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 // to the uri, and the target doesn't. Let's now give this to
4589 // the target.
4590
Joe Onorato8a9b2202010-02-26 18:56:32 -08004591 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004592 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 HashMap<Uri, UriPermission> targetUris
4595 = mGrantedUriPermissions.get(targetUid);
4596 if (targetUris == null) {
4597 targetUris = new HashMap<Uri, UriPermission>();
4598 mGrantedUriPermissions.put(targetUid, targetUris);
4599 }
4600
4601 UriPermission perm = targetUris.get(uri);
4602 if (perm == null) {
4603 perm = new UriPermission(targetUid, uri);
4604 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004605 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004608 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004609 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004610 } else {
4611 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4612 perm.readOwners.add(owner);
4613 owner.addReadPermission(perm);
4614 }
4615 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4616 perm.writeOwners.add(owner);
4617 owner.addWritePermission(perm);
4618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 }
4620 }
4621
Dianne Hackborn39792d22010-08-19 18:01:52 -07004622 void grantUriPermissionLocked(int callingUid,
4623 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004624 if (targetPkg == null) {
4625 throw new NullPointerException("targetPkg");
4626 }
4627
Dianne Hackborn39792d22010-08-19 18:01:52 -07004628 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4629 if (targetUid < 0) {
4630 return;
4631 }
4632
4633 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4634 }
4635
4636 /**
4637 * Like checkGrantUriPermissionLocked, but takes an Intent.
4638 */
4639 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4640 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004641 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004642 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004643 + " from " + intent + "; flags=0x"
4644 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4645
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004646 if (targetPkg == null) {
4647 throw new NullPointerException("targetPkg");
4648 }
4649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004651 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004652 }
4653 Uri data = intent.getData();
4654 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004655 return -1;
4656 }
4657 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4658 intent.getFlags());
4659 }
4660
4661 /**
4662 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4663 */
4664 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4665 String targetPkg, Intent intent, UriPermissionOwner owner) {
4666 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4667 intent.getFlags(), owner);
4668 }
4669
4670 void grantUriPermissionFromIntentLocked(int callingUid,
4671 String targetPkg, Intent intent, UriPermissionOwner owner) {
4672 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4673 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004674 return;
4675 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004676
4677 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 }
4679
4680 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4681 Uri uri, int modeFlags) {
4682 synchronized(this) {
4683 final ProcessRecord r = getRecordForAppLocked(caller);
4684 if (r == null) {
4685 throw new SecurityException("Unable to find app for caller "
4686 + caller
4687 + " when granting permission to uri " + uri);
4688 }
4689 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004690 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 }
4692 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004693 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 }
4695
4696 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4697 null);
4698 }
4699 }
4700
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004701 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4703 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4704 HashMap<Uri, UriPermission> perms
4705 = mGrantedUriPermissions.get(perm.uid);
4706 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004707 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004708 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004709 perms.remove(perm.uri);
4710 if (perms.size() == 0) {
4711 mGrantedUriPermissions.remove(perm.uid);
4712 }
4713 }
4714 }
4715 }
4716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4718 int modeFlags) {
4719 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4720 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4721 if (modeFlags == 0) {
4722 return;
4723 }
4724
Joe Onorato8a9b2202010-02-26 18:56:32 -08004725 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004726 "Revoking all granted permissions to " + uri);
4727
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004728 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004729
4730 final String authority = uri.getAuthority();
4731 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004732 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004733 if (cpr != null) {
4734 pi = cpr.info;
4735 } else {
4736 try {
4737 pi = pm.resolveContentProvider(authority,
4738 PackageManager.GET_URI_PERMISSION_PATTERNS);
4739 } catch (RemoteException ex) {
4740 }
4741 }
4742 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004743 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004744 return;
4745 }
4746
4747 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004748 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 // Right now, if you are not the original owner of the permission,
4750 // you are not allowed to revoke it.
4751 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4752 throw new SecurityException("Uid " + callingUid
4753 + " does not have permission to uri " + uri);
4754 //}
4755 }
4756
4757 // Go through all of the permissions and remove any that match.
4758 final List<String> SEGMENTS = uri.getPathSegments();
4759 if (SEGMENTS != null) {
4760 final int NS = SEGMENTS.size();
4761 int N = mGrantedUriPermissions.size();
4762 for (int i=0; i<N; i++) {
4763 HashMap<Uri, UriPermission> perms
4764 = mGrantedUriPermissions.valueAt(i);
4765 Iterator<UriPermission> it = perms.values().iterator();
4766 toploop:
4767 while (it.hasNext()) {
4768 UriPermission perm = it.next();
4769 Uri targetUri = perm.uri;
4770 if (!authority.equals(targetUri.getAuthority())) {
4771 continue;
4772 }
4773 List<String> targetSegments = targetUri.getPathSegments();
4774 if (targetSegments == null) {
4775 continue;
4776 }
4777 if (targetSegments.size() < NS) {
4778 continue;
4779 }
4780 for (int j=0; j<NS; j++) {
4781 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4782 continue toploop;
4783 }
4784 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004785 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004786 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004787 perm.clearModes(modeFlags);
4788 if (perm.modeFlags == 0) {
4789 it.remove();
4790 }
4791 }
4792 if (perms.size() == 0) {
4793 mGrantedUriPermissions.remove(
4794 mGrantedUriPermissions.keyAt(i));
4795 N--;
4796 i--;
4797 }
4798 }
4799 }
4800 }
4801
4802 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4803 int modeFlags) {
4804 synchronized(this) {
4805 final ProcessRecord r = getRecordForAppLocked(caller);
4806 if (r == null) {
4807 throw new SecurityException("Unable to find app for caller "
4808 + caller
4809 + " when revoking permission to uri " + uri);
4810 }
4811 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004812 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004813 return;
4814 }
4815
4816 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4817 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4818 if (modeFlags == 0) {
4819 return;
4820 }
4821
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004822 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004823
4824 final String authority = uri.getAuthority();
4825 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004826 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004827 if (cpr != null) {
4828 pi = cpr.info;
4829 } else {
4830 try {
4831 pi = pm.resolveContentProvider(authority,
4832 PackageManager.GET_URI_PERMISSION_PATTERNS);
4833 } catch (RemoteException ex) {
4834 }
4835 }
4836 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004837 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004838 return;
4839 }
4840
4841 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4842 }
4843 }
4844
Dianne Hackborn7e269642010-08-25 19:50:20 -07004845 @Override
4846 public IBinder newUriPermissionOwner(String name) {
4847 synchronized(this) {
4848 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4849 return owner.getExternalTokenLocked();
4850 }
4851 }
4852
4853 @Override
4854 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4855 Uri uri, int modeFlags) {
4856 synchronized(this) {
4857 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4858 if (owner == null) {
4859 throw new IllegalArgumentException("Unknown owner: " + token);
4860 }
4861 if (fromUid != Binder.getCallingUid()) {
4862 if (Binder.getCallingUid() != Process.myUid()) {
4863 // Only system code can grant URI permissions on behalf
4864 // of other users.
4865 throw new SecurityException("nice try");
4866 }
4867 }
4868 if (targetPkg == null) {
4869 throw new IllegalArgumentException("null target");
4870 }
4871 if (uri == null) {
4872 throw new IllegalArgumentException("null uri");
4873 }
4874
4875 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4876 }
4877 }
4878
4879 @Override
4880 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4881 synchronized(this) {
4882 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4883 if (owner == null) {
4884 throw new IllegalArgumentException("Unknown owner: " + token);
4885 }
4886
4887 if (uri == null) {
4888 owner.removeUriPermissionsLocked(mode);
4889 } else {
4890 owner.removeUriPermissionLocked(uri, mode);
4891 }
4892 }
4893 }
4894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4896 synchronized (this) {
4897 ProcessRecord app =
4898 who != null ? getRecordForAppLocked(who) : null;
4899 if (app == null) return;
4900
4901 Message msg = Message.obtain();
4902 msg.what = WAIT_FOR_DEBUGGER_MSG;
4903 msg.obj = app;
4904 msg.arg1 = waiting ? 1 : 0;
4905 mHandler.sendMessage(msg);
4906 }
4907 }
4908
4909 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4910 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004911 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004913 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004914 }
4915
4916 // =========================================================
4917 // TASK MANAGEMENT
4918 // =========================================================
4919
4920 public List getTasks(int maxNum, int flags,
4921 IThumbnailReceiver receiver) {
4922 ArrayList list = new ArrayList();
4923
4924 PendingThumbnailsRecord pending = null;
4925 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004926 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927
4928 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004929 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004930 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4931 + ", receiver=" + receiver);
4932
4933 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4934 != PackageManager.PERMISSION_GRANTED) {
4935 if (receiver != null) {
4936 // If the caller wants to wait for pending thumbnails,
4937 // it ain't gonna get them.
4938 try {
4939 receiver.finished();
4940 } catch (RemoteException ex) {
4941 }
4942 }
4943 String msg = "Permission Denial: getTasks() from pid="
4944 + Binder.getCallingPid()
4945 + ", uid=" + Binder.getCallingUid()
4946 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004947 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 throw new SecurityException(msg);
4949 }
4950
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004951 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004952 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004953 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004954 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004955 TaskRecord curTask = null;
4956 int numActivities = 0;
4957 int numRunning = 0;
4958 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004959 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004961 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004962
4963 // Initialize state for next task if needed.
4964 if (top == null ||
4965 (top.state == ActivityState.INITIALIZING
4966 && top.task == r.task)) {
4967 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004968 curTask = r.task;
4969 numActivities = numRunning = 0;
4970 }
4971
4972 // Add 'r' into the current task.
4973 numActivities++;
4974 if (r.app != null && r.app.thread != null) {
4975 numRunning++;
4976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977
Joe Onorato8a9b2202010-02-26 18:56:32 -08004978 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004979 TAG, r.intent.getComponent().flattenToShortString()
4980 + ": task=" + r.task);
4981
4982 // If the next one is a different task, generate a new
4983 // TaskInfo entry for what we have.
4984 if (next == null || next.task != curTask) {
4985 ActivityManager.RunningTaskInfo ci
4986 = new ActivityManager.RunningTaskInfo();
4987 ci.id = curTask.taskId;
4988 ci.baseActivity = r.intent.getComponent();
4989 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07004990 if (top.thumbHolder != null) {
4991 ci.description = top.thumbHolder.lastDescription;
4992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 ci.numActivities = numActivities;
4994 ci.numRunning = numRunning;
4995 //System.out.println(
4996 // "#" + maxNum + ": " + " descr=" + ci.description);
4997 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004998 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 TAG, "State=" + top.state + "Idle=" + top.idle
5000 + " app=" + top.app
5001 + " thr=" + (top.app != null ? top.app.thread : null));
5002 if (top.state == ActivityState.RESUMED
5003 || top.state == ActivityState.PAUSING) {
5004 if (top.idle && top.app != null
5005 && top.app.thread != null) {
5006 topRecord = top;
5007 topThumbnail = top.app.thread;
5008 } else {
5009 top.thumbnailNeeded = true;
5010 }
5011 }
5012 if (pending == null) {
5013 pending = new PendingThumbnailsRecord(receiver);
5014 }
5015 pending.pendingRecords.add(top);
5016 }
5017 list.add(ci);
5018 maxNum--;
5019 top = null;
5020 }
5021 }
5022
5023 if (pending != null) {
5024 mPendingThumbnails.add(pending);
5025 }
5026 }
5027
Joe Onorato8a9b2202010-02-26 18:56:32 -08005028 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005029
5030 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005031 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 try {
5033 topThumbnail.requestThumbnail(topRecord);
5034 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005035 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005036 sendPendingThumbnail(null, topRecord, null, null, true);
5037 }
5038 }
5039
5040 if (pending == null && receiver != null) {
5041 // In this case all thumbnails were available and the client
5042 // is being asked to be told when the remaining ones come in...
5043 // which is unusually, since the top-most currently running
5044 // activity should never have a canned thumbnail! Oh well.
5045 try {
5046 receiver.finished();
5047 } catch (RemoteException ex) {
5048 }
5049 }
5050
5051 return list;
5052 }
5053
5054 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5055 int flags) {
5056 synchronized (this) {
5057 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5058 "getRecentTasks()");
5059
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005060 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 final int N = mRecentTasks.size();
5063 ArrayList<ActivityManager.RecentTaskInfo> res
5064 = new ArrayList<ActivityManager.RecentTaskInfo>(
5065 maxNum < N ? maxNum : N);
5066 for (int i=0; i<N && maxNum > 0; i++) {
5067 TaskRecord tr = mRecentTasks.get(i);
5068 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
5069 || (tr.intent == null)
5070 || ((tr.intent.getFlags()
5071 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5072 ActivityManager.RecentTaskInfo rti
5073 = new ActivityManager.RecentTaskInfo();
5074 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005075 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005076 rti.baseIntent = new Intent(
5077 tr.intent != null ? tr.intent : tr.affinityIntent);
5078 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005079 rti.description = tr.lastDescription;
5080
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005081 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5082 // Check whether this activity is currently available.
5083 try {
5084 if (rti.origActivity != null) {
5085 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5086 continue;
5087 }
5088 } else if (rti.baseIntent != null) {
5089 if (pm.queryIntentActivities(rti.baseIntent,
5090 null, 0) == null) {
5091 continue;
5092 }
5093 }
5094 } catch (RemoteException e) {
5095 // Will never happen.
5096 }
5097 }
5098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 res.add(rti);
5100 maxNum--;
5101 }
5102 }
5103 return res;
5104 }
5105 }
5106
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005107 private TaskRecord taskForIdLocked(int id) {
5108 final int N = mRecentTasks.size();
5109 for (int i=0; i<N; i++) {
5110 TaskRecord tr = mRecentTasks.get(i);
5111 if (tr.taskId == id) {
5112 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005113 }
5114 }
5115 return null;
5116 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005117
5118 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5119 synchronized (this) {
5120 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5121 "getTaskThumbnails()");
5122 TaskRecord tr = taskForIdLocked(id);
5123 if (tr != null) {
5124 return mMainStack.getTaskThumbnailsLocked(tr);
5125 }
5126 }
5127 return null;
5128 }
5129
5130 public boolean removeSubTask(int taskId, int subTaskIndex) {
5131 synchronized (this) {
5132 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5133 "removeSubTask()");
5134 long ident = Binder.clearCallingIdentity();
5135 try {
5136 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5137 } finally {
5138 Binder.restoreCallingIdentity(ident);
5139 }
5140 }
5141 }
5142
5143 private void removeTaskProcessesLocked(ActivityRecord root) {
5144 TaskRecord tr = root.task;
5145 Intent baseIntent = new Intent(
5146 tr.intent != null ? tr.intent : tr.affinityIntent);
5147 ComponentName component = baseIntent.getComponent();
5148 if (component == null) {
5149 Slog.w(TAG, "Now component for base intent of task: " + tr);
5150 return;
5151 }
5152
5153 // Find any running services associated with this app.
5154 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5155 for (ServiceRecord sr : mServices.values()) {
5156 if (sr.packageName.equals(component.getPackageName())) {
5157 services.add(sr);
5158 }
5159 }
5160
5161 // Take care of any running services associated with the app.
5162 for (int i=0; i<services.size(); i++) {
5163 ServiceRecord sr = services.get(i);
5164 if (sr.startRequested) {
5165 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
5166 stopServiceLocked(sr);
5167 } else {
5168 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5169 sr.makeNextStartId(), baseIntent, -1));
5170 if (sr.app != null && sr.app.thread != null) {
5171 sendServiceArgsLocked(sr, false);
5172 }
5173 }
5174 }
5175 }
5176
5177 // Find any running processes associated with this app.
5178 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5179 SparseArray<ProcessRecord> appProcs
5180 = mProcessNames.getMap().get(component.getPackageName());
5181 if (appProcs != null) {
5182 for (int i=0; i<appProcs.size(); i++) {
5183 procs.add(appProcs.valueAt(i));
5184 }
5185 }
5186
5187 // Kill the running processes.
5188 for (int i=0; i<procs.size(); i++) {
5189 ProcessRecord pr = procs.get(i);
5190 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5191 Slog.i(TAG, "Killing " + pr + ": remove task");
5192 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5193 pr.processName, pr.setAdj, "remove task");
5194 Process.killProcessQuiet(pr.pid);
5195 } else {
5196 pr.waitingToKill = "remove task";
5197 }
5198 }
5199 }
5200
5201 public boolean removeTask(int taskId, int flags) {
5202 synchronized (this) {
5203 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5204 "removeTask()");
5205 long ident = Binder.clearCallingIdentity();
5206 try {
5207 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5208 if (r != null) {
5209 mRecentTasks.remove(r.task);
5210
5211 if ((flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0) {
5212 removeTaskProcessesLocked(r);
5213 }
5214
5215 return true;
5216 }
5217 } finally {
5218 Binder.restoreCallingIdentity(ident);
5219 }
5220 }
5221 return false;
5222 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5225 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005226 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005227 TaskRecord jt = startTask;
5228
5229 // First look backwards
5230 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005231 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 if (r.task != jt) {
5233 jt = r.task;
5234 if (affinity.equals(jt.affinity)) {
5235 return j;
5236 }
5237 }
5238 }
5239
5240 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005241 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005242 jt = startTask;
5243 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005244 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 if (r.task != jt) {
5246 if (affinity.equals(jt.affinity)) {
5247 return j;
5248 }
5249 jt = r.task;
5250 }
5251 }
5252
5253 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005254 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 return N-1;
5256 }
5257
5258 return -1;
5259 }
5260
5261 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005262 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005264 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005265 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5266 "moveTaskToFront()");
5267
5268 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005269 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5270 Binder.getCallingUid(), "Task to front")) {
5271 return;
5272 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005273 final long origId = Binder.clearCallingIdentity();
5274 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005275 TaskRecord tr = taskForIdLocked(task);
5276 if (tr != null) {
5277 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5278 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005279 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005280 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5281 // Caller wants the home activity moved with it. To accomplish this,
5282 // we'll just move the home task to the top first.
5283 mMainStack.moveHomeToFrontLocked();
5284 }
5285 mMainStack.moveTaskToFrontLocked(tr, null);
5286 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005288 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5289 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005290 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005291 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5292 mMainStack.mUserLeaving = true;
5293 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005294 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5295 // Caller wants the home activity moved with it. To accomplish this,
5296 // we'll just move the home task to the top first.
5297 mMainStack.moveHomeToFrontLocked();
5298 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005299 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005300 return;
5301 }
5302 }
5303 } finally {
5304 Binder.restoreCallingIdentity(origId);
5305 }
5306 }
5307 }
5308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005309 public void moveTaskToBack(int task) {
5310 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5311 "moveTaskToBack()");
5312
5313 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005314 if (mMainStack.mResumedActivity != null
5315 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005316 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5317 Binder.getCallingUid(), "Task to back")) {
5318 return;
5319 }
5320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005322 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 Binder.restoreCallingIdentity(origId);
5324 }
5325 }
5326
5327 /**
5328 * Moves an activity, and all of the other activities within the same task, to the bottom
5329 * of the history stack. The activity's order within the task is unchanged.
5330 *
5331 * @param token A reference to the activity we wish to move
5332 * @param nonRoot If false then this only works if the activity is the root
5333 * of a task; if true it will work for any activity in a task.
5334 * @return Returns true if the move completed, false if not.
5335 */
5336 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5337 synchronized(this) {
5338 final long origId = Binder.clearCallingIdentity();
5339 int taskId = getTaskForActivityLocked(token, !nonRoot);
5340 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005341 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 }
5343 Binder.restoreCallingIdentity(origId);
5344 }
5345 return false;
5346 }
5347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005348 public void moveTaskBackwards(int task) {
5349 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5350 "moveTaskBackwards()");
5351
5352 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005353 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5354 Binder.getCallingUid(), "Task backwards")) {
5355 return;
5356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 final long origId = Binder.clearCallingIdentity();
5358 moveTaskBackwardsLocked(task);
5359 Binder.restoreCallingIdentity(origId);
5360 }
5361 }
5362
5363 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005364 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365 }
5366
5367 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5368 synchronized(this) {
5369 return getTaskForActivityLocked(token, onlyRoot);
5370 }
5371 }
5372
5373 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005374 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 TaskRecord lastTask = null;
5376 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005377 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005378 if (r == token) {
5379 if (!onlyRoot || lastTask != r.task) {
5380 return r.task.taskId;
5381 }
5382 return -1;
5383 }
5384 lastTask = r.task;
5385 }
5386
5387 return -1;
5388 }
5389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 public void finishOtherInstances(IBinder token, ComponentName className) {
5391 synchronized(this) {
5392 final long origId = Binder.clearCallingIdentity();
5393
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005394 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005395 TaskRecord lastTask = null;
5396 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005397 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005398 if (r.realActivity.equals(className)
5399 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005400 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 null, "others")) {
5402 i--;
5403 N--;
5404 }
5405 }
5406 lastTask = r.task;
5407 }
5408
5409 Binder.restoreCallingIdentity(origId);
5410 }
5411 }
5412
5413 // =========================================================
5414 // THUMBNAILS
5415 // =========================================================
5416
5417 public void reportThumbnail(IBinder token,
5418 Bitmap thumbnail, CharSequence description) {
5419 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5420 final long origId = Binder.clearCallingIdentity();
5421 sendPendingThumbnail(null, token, thumbnail, description, true);
5422 Binder.restoreCallingIdentity(origId);
5423 }
5424
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005425 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005426 Bitmap thumbnail, CharSequence description, boolean always) {
5427 TaskRecord task = null;
5428 ArrayList receivers = null;
5429
5430 //System.out.println("Send pending thumbnail: " + r);
5431
5432 synchronized(this) {
5433 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005434 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005435 if (index < 0) {
5436 return;
5437 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005438 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005439 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005440 if (thumbnail == null && r.thumbHolder != null) {
5441 thumbnail = r.thumbHolder.lastThumbnail;
5442 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005443 }
5444 if (thumbnail == null && !always) {
5445 // If there is no thumbnail, and this entry is not actually
5446 // going away, then abort for now and pick up the next
5447 // thumbnail we get.
5448 return;
5449 }
5450 task = r.task;
5451
5452 int N = mPendingThumbnails.size();
5453 int i=0;
5454 while (i<N) {
5455 PendingThumbnailsRecord pr =
5456 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5457 //System.out.println("Looking in " + pr.pendingRecords);
5458 if (pr.pendingRecords.remove(r)) {
5459 if (receivers == null) {
5460 receivers = new ArrayList();
5461 }
5462 receivers.add(pr);
5463 if (pr.pendingRecords.size() == 0) {
5464 pr.finished = true;
5465 mPendingThumbnails.remove(i);
5466 N--;
5467 continue;
5468 }
5469 }
5470 i++;
5471 }
5472 }
5473
5474 if (receivers != null) {
5475 final int N = receivers.size();
5476 for (int i=0; i<N; i++) {
5477 try {
5478 PendingThumbnailsRecord pr =
5479 (PendingThumbnailsRecord)receivers.get(i);
5480 pr.receiver.newThumbnail(
5481 task != null ? task.taskId : -1, thumbnail, description);
5482 if (pr.finished) {
5483 pr.receiver.finished();
5484 }
5485 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005486 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005487 }
5488 }
5489 }
5490 }
5491
5492 // =========================================================
5493 // CONTENT PROVIDERS
5494 // =========================================================
5495
5496 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5497 List providers = null;
5498 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005499 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005500 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005501 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005502 } catch (RemoteException ex) {
5503 }
5504 if (providers != null) {
5505 final int N = providers.size();
5506 for (int i=0; i<N; i++) {
5507 ProviderInfo cpi =
5508 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005509 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 if (cpr == null) {
5511 cpr = new ContentProviderRecord(cpi, app.info);
5512 mProvidersByClass.put(cpi.name, cpr);
5513 }
5514 app.pubProviders.put(cpi.name, cpr);
5515 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005516 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005517 }
5518 }
5519 return providers;
5520 }
5521
5522 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005523 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005524 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5525 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5526 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005527 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005528 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005529 return null;
5530 }
5531 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005532 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005533 == PackageManager.PERMISSION_GRANTED) {
5534 return null;
5535 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005536
5537 PathPermission[] pps = cpi.pathPermissions;
5538 if (pps != null) {
5539 int i = pps.length;
5540 while (i > 0) {
5541 i--;
5542 PathPermission pp = pps[i];
5543 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005544 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005545 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005546 return null;
5547 }
5548 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005549 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005550 == PackageManager.PERMISSION_GRANTED) {
5551 return null;
5552 }
5553 }
5554 }
5555
Dianne Hackbornb424b632010-08-18 15:59:05 -07005556 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5557 if (perms != null) {
5558 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5559 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5560 return null;
5561 }
5562 }
5563 }
5564
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005565 String msg;
5566 if (!cpi.exported) {
5567 msg = "Permission Denial: opening provider " + cpi.name
5568 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5569 + ", uid=" + callingUid + ") that is not exported from uid "
5570 + cpi.applicationInfo.uid;
5571 } else {
5572 msg = "Permission Denial: opening provider " + cpi.name
5573 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5574 + ", uid=" + callingUid + ") requires "
5575 + cpi.readPermission + " or " + cpi.writePermission;
5576 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005577 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 return msg;
5579 }
5580
5581 private final ContentProviderHolder getContentProviderImpl(
5582 IApplicationThread caller, String name) {
5583 ContentProviderRecord cpr;
5584 ProviderInfo cpi = null;
5585
5586 synchronized(this) {
5587 ProcessRecord r = null;
5588 if (caller != null) {
5589 r = getRecordForAppLocked(caller);
5590 if (r == null) {
5591 throw new SecurityException(
5592 "Unable to find app for caller " + caller
5593 + " (pid=" + Binder.getCallingPid()
5594 + ") when getting content provider " + name);
5595 }
5596 }
5597
5598 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005599 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005600 if (cpr != null) {
5601 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005602 String msg;
5603 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5604 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005605 }
5606
5607 if (r != null && cpr.canRunHere(r)) {
5608 // This provider has been published or is in the process
5609 // of being published... but it is also allowed to run
5610 // in the caller's process, so don't make a connection
5611 // and just let the caller instantiate its own instance.
5612 if (cpr.provider != null) {
5613 // don't give caller the provider object, it needs
5614 // to make its own.
5615 cpr = new ContentProviderRecord(cpr);
5616 }
5617 return cpr;
5618 }
5619
5620 final long origId = Binder.clearCallingIdentity();
5621
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005622 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 // return it right away.
5624 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005625 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005626 "Adding provider requested by "
5627 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005628 + cpr.info.processName);
5629 Integer cnt = r.conProviders.get(cpr);
5630 if (cnt == null) {
5631 r.conProviders.put(cpr, new Integer(1));
5632 } else {
5633 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005635 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005636 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5637 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005638 // make sure to count it as being accessed and thus
5639 // back up on the LRU list. This is good because
5640 // content providers are often expensive to start.
5641 updateLruProcessLocked(cpr.app, false, true);
5642 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005643 } else {
5644 cpr.externals++;
5645 }
5646
5647 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005648 updateOomAdjLocked(cpr.app);
5649 }
5650
5651 Binder.restoreCallingIdentity(origId);
5652
5653 } else {
5654 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005655 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005656 resolveContentProvider(name,
5657 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005658 } catch (RemoteException ex) {
5659 }
5660 if (cpi == null) {
5661 return null;
5662 }
5663
Dianne Hackbornb424b632010-08-18 15:59:05 -07005664 String msg;
5665 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5666 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005667 }
5668
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005669 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005670 && !cpi.processName.equals("system")) {
5671 // If this content provider does not run in the system
5672 // process, and the system is not yet ready to run other
5673 // processes, then fail fast instead of hanging.
5674 throw new IllegalArgumentException(
5675 "Attempt to launch content provider before system ready");
5676 }
5677
Dianne Hackborn860755f2010-06-03 18:47:52 -07005678 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 final boolean firstClass = cpr == null;
5680 if (firstClass) {
5681 try {
5682 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005683 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005684 getApplicationInfo(
5685 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005686 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005687 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005688 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005689 + cpi.name);
5690 return null;
5691 }
5692 cpr = new ContentProviderRecord(cpi, ai);
5693 } catch (RemoteException ex) {
5694 // pm is in same process, this will never happen.
5695 }
5696 }
5697
5698 if (r != null && cpr.canRunHere(r)) {
5699 // If this is a multiprocess provider, then just return its
5700 // info and allow the caller to instantiate it. Only do
5701 // this if the provider is the same user as the caller's
5702 // process, or can run as root (so can be in any process).
5703 return cpr;
5704 }
5705
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005706 if (DEBUG_PROVIDER) {
5707 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005708 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005709 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005710 }
5711
5712 // This is single process, and our app is now connecting to it.
5713 // See if we are already in the process of launching this
5714 // provider.
5715 final int N = mLaunchingProviders.size();
5716 int i;
5717 for (i=0; i<N; i++) {
5718 if (mLaunchingProviders.get(i) == cpr) {
5719 break;
5720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005721 }
5722
5723 // If the provider is not already being launched, then get it
5724 // started.
5725 if (i >= N) {
5726 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005727
5728 try {
5729 // Content provider is now in use, its package can't be stopped.
5730 try {
5731 AppGlobals.getPackageManager().setPackageStoppedState(
5732 cpr.appInfo.packageName, false);
5733 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005734 } catch (IllegalArgumentException e) {
5735 Slog.w(TAG, "Failed trying to unstop package "
5736 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005737 }
5738
5739 ProcessRecord proc = startProcessLocked(cpi.processName,
5740 cpr.appInfo, false, 0, "content provider",
5741 new ComponentName(cpi.applicationInfo.packageName,
5742 cpi.name), false);
5743 if (proc == null) {
5744 Slog.w(TAG, "Unable to launch app "
5745 + cpi.applicationInfo.packageName + "/"
5746 + cpi.applicationInfo.uid + " for provider "
5747 + name + ": process is bad");
5748 return null;
5749 }
5750 cpr.launchingApp = proc;
5751 mLaunchingProviders.add(cpr);
5752 } finally {
5753 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005755 }
5756
5757 // Make sure the provider is published (the same provider class
5758 // may be published under multiple names).
5759 if (firstClass) {
5760 mProvidersByClass.put(cpi.name, cpr);
5761 }
5762 mProvidersByName.put(name, cpr);
5763
5764 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005765 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005766 "Adding provider requested by "
5767 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005768 + cpr.info.processName);
5769 Integer cnt = r.conProviders.get(cpr);
5770 if (cnt == null) {
5771 r.conProviders.put(cpr, new Integer(1));
5772 } else {
5773 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005775 cpr.clients.add(r);
5776 } else {
5777 cpr.externals++;
5778 }
5779 }
5780 }
5781
5782 // Wait for the provider to be published...
5783 synchronized (cpr) {
5784 while (cpr.provider == null) {
5785 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005786 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005787 + cpi.applicationInfo.packageName + "/"
5788 + cpi.applicationInfo.uid + " for provider "
5789 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005790 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 cpi.applicationInfo.packageName,
5792 cpi.applicationInfo.uid, name);
5793 return null;
5794 }
5795 try {
5796 cpr.wait();
5797 } catch (InterruptedException ex) {
5798 }
5799 }
5800 }
5801 return cpr;
5802 }
5803
5804 public final ContentProviderHolder getContentProvider(
5805 IApplicationThread caller, String name) {
5806 if (caller == null) {
5807 String msg = "null IApplicationThread when getting content provider "
5808 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005809 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005810 throw new SecurityException(msg);
5811 }
5812
5813 return getContentProviderImpl(caller, name);
5814 }
5815
5816 private ContentProviderHolder getContentProviderExternal(String name) {
5817 return getContentProviderImpl(null, name);
5818 }
5819
5820 /**
5821 * Drop a content provider from a ProcessRecord's bookkeeping
5822 * @param cpr
5823 */
5824 public void removeContentProvider(IApplicationThread caller, String name) {
5825 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005826 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005827 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005828 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005829 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005830 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005831 return;
5832 }
5833 final ProcessRecord r = getRecordForAppLocked(caller);
5834 if (r == null) {
5835 throw new SecurityException(
5836 "Unable to find app for caller " + caller +
5837 " when removing content provider " + name);
5838 }
5839 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005840 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005841 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005842 + r.info.processName + " from process "
5843 + localCpr.appInfo.processName);
5844 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005845 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005846 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005847 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005848 return;
5849 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005850 Integer cnt = r.conProviders.get(localCpr);
5851 if (cnt == null || cnt.intValue() <= 1) {
5852 localCpr.clients.remove(r);
5853 r.conProviders.remove(localCpr);
5854 } else {
5855 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005857 }
5858 updateOomAdjLocked();
5859 }
5860 }
5861
5862 private void removeContentProviderExternal(String name) {
5863 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005864 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865 if(cpr == null) {
5866 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005867 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 return;
5869 }
5870
5871 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005872 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005873 localCpr.externals--;
5874 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005875 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005876 }
5877 updateOomAdjLocked();
5878 }
5879 }
5880
5881 public final void publishContentProviders(IApplicationThread caller,
5882 List<ContentProviderHolder> providers) {
5883 if (providers == null) {
5884 return;
5885 }
5886
5887 synchronized(this) {
5888 final ProcessRecord r = getRecordForAppLocked(caller);
5889 if (r == null) {
5890 throw new SecurityException(
5891 "Unable to find app for caller " + caller
5892 + " (pid=" + Binder.getCallingPid()
5893 + ") when publishing content providers");
5894 }
5895
5896 final long origId = Binder.clearCallingIdentity();
5897
5898 final int N = providers.size();
5899 for (int i=0; i<N; i++) {
5900 ContentProviderHolder src = providers.get(i);
5901 if (src == null || src.info == null || src.provider == null) {
5902 continue;
5903 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005904 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005905 if (dst != null) {
5906 mProvidersByClass.put(dst.info.name, dst);
5907 String names[] = dst.info.authority.split(";");
5908 for (int j = 0; j < names.length; j++) {
5909 mProvidersByName.put(names[j], dst);
5910 }
5911
5912 int NL = mLaunchingProviders.size();
5913 int j;
5914 for (j=0; j<NL; j++) {
5915 if (mLaunchingProviders.get(j) == dst) {
5916 mLaunchingProviders.remove(j);
5917 j--;
5918 NL--;
5919 }
5920 }
5921 synchronized (dst) {
5922 dst.provider = src.provider;
5923 dst.app = r;
5924 dst.notifyAll();
5925 }
5926 updateOomAdjLocked(r);
5927 }
5928 }
5929
5930 Binder.restoreCallingIdentity(origId);
5931 }
5932 }
5933
5934 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005935 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005936 synchronized (mSelf) {
5937 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5938 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005939 if (providers != null) {
5940 for (int i=providers.size()-1; i>=0; i--) {
5941 ProviderInfo pi = (ProviderInfo)providers.get(i);
5942 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5943 Slog.w(TAG, "Not installing system proc provider " + pi.name
5944 + ": not system .apk");
5945 providers.remove(i);
5946 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005947 }
5948 }
5949 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005950 if (providers != null) {
5951 mSystemThread.installSystemProviders(providers);
5952 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005953
5954 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 }
5956
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005957 /**
5958 * Allows app to retrieve the MIME type of a URI without having permission
5959 * to access its content provider.
5960 *
5961 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5962 *
5963 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5964 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5965 */
5966 public String getProviderMimeType(Uri uri) {
5967 final String name = uri.getAuthority();
5968 final long ident = Binder.clearCallingIdentity();
5969 ContentProviderHolder holder = null;
5970
5971 try {
5972 holder = getContentProviderExternal(name);
5973 if (holder != null) {
5974 return holder.provider.getType(uri);
5975 }
5976 } catch (RemoteException e) {
5977 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5978 return null;
5979 } finally {
5980 if (holder != null) {
5981 removeContentProviderExternal(name);
5982 }
5983 Binder.restoreCallingIdentity(ident);
5984 }
5985
5986 return null;
5987 }
5988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005989 // =========================================================
5990 // GLOBAL MANAGEMENT
5991 // =========================================================
5992
5993 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5994 ApplicationInfo info, String customProcess) {
5995 String proc = customProcess != null ? customProcess : info.processName;
5996 BatteryStatsImpl.Uid.Proc ps = null;
5997 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5998 synchronized (stats) {
5999 ps = stats.getProcessStatsLocked(info.uid, proc);
6000 }
6001 return new ProcessRecord(ps, thread, info, proc);
6002 }
6003
6004 final ProcessRecord addAppLocked(ApplicationInfo info) {
6005 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
6006
6007 if (app == null) {
6008 app = newProcessRecordLocked(null, info, null);
6009 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006010 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006011 }
6012
Dianne Hackborne7f97212011-02-24 14:40:20 -08006013 // This package really, really can not be stopped.
6014 try {
6015 AppGlobals.getPackageManager().setPackageStoppedState(
6016 info.packageName, false);
6017 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006018 } catch (IllegalArgumentException e) {
6019 Slog.w(TAG, "Failed trying to unstop package "
6020 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006021 }
6022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006023 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6024 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6025 app.persistent = true;
6026 app.maxAdj = CORE_SERVER_ADJ;
6027 }
6028 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6029 mPersistentStartingProcesses.add(app);
6030 startProcessLocked(app, "added application", app.processName);
6031 }
6032
6033 return app;
6034 }
6035
6036 public void unhandledBack() {
6037 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6038 "unhandledBack()");
6039
6040 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006041 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006042 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 TAG, "Performing unhandledBack(): stack size = " + count);
6044 if (count > 1) {
6045 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006046 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6048 Binder.restoreCallingIdentity(origId);
6049 }
6050 }
6051 }
6052
6053 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6054 String name = uri.getAuthority();
6055 ContentProviderHolder cph = getContentProviderExternal(name);
6056 ParcelFileDescriptor pfd = null;
6057 if (cph != null) {
6058 // We record the binder invoker's uid in thread-local storage before
6059 // going to the content provider to open the file. Later, in the code
6060 // that handles all permissions checks, we look for this uid and use
6061 // that rather than the Activity Manager's own uid. The effect is that
6062 // we do the check against the caller's permissions even though it looks
6063 // to the content provider like the Activity Manager itself is making
6064 // the request.
6065 sCallerIdentity.set(new Identity(
6066 Binder.getCallingPid(), Binder.getCallingUid()));
6067 try {
6068 pfd = cph.provider.openFile(uri, "r");
6069 } catch (FileNotFoundException e) {
6070 // do nothing; pfd will be returned null
6071 } finally {
6072 // Ensure that whatever happens, we clean up the identity state
6073 sCallerIdentity.remove();
6074 }
6075
6076 // We've got the fd now, so we're done with the provider.
6077 removeContentProviderExternal(name);
6078 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006079 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006080 }
6081 return pfd;
6082 }
6083
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006084 // Actually is sleeping or shutting down or whatever else in the future
6085 // is an inactive state.
6086 public boolean isSleeping() {
6087 return mSleeping || mShuttingDown;
6088 }
6089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006090 public void goingToSleep() {
6091 synchronized(this) {
6092 mSleeping = true;
6093 mWindowManager.setEventDispatching(false);
6094
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006095 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006096
6097 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006098 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006099 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6100 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006101 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 }
6103 }
6104
Dianne Hackborn55280a92009-05-07 15:53:46 -07006105 public boolean shutdown(int timeout) {
6106 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6107 != PackageManager.PERMISSION_GRANTED) {
6108 throw new SecurityException("Requires permission "
6109 + android.Manifest.permission.SHUTDOWN);
6110 }
6111
6112 boolean timedout = false;
6113
6114 synchronized(this) {
6115 mShuttingDown = true;
6116 mWindowManager.setEventDispatching(false);
6117
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006118 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006119 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006120 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006121 while (mMainStack.mResumedActivity != null
6122 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006123 long delay = endTime - System.currentTimeMillis();
6124 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006125 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006126 timedout = true;
6127 break;
6128 }
6129 try {
6130 this.wait();
6131 } catch (InterruptedException e) {
6132 }
6133 }
6134 }
6135 }
6136
6137 mUsageStatsService.shutdown();
6138 mBatteryStatsService.shutdown();
6139
6140 return timedout;
6141 }
6142
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006143 public final void activitySlept(IBinder token) {
6144 if (localLOGV) Slog.v(
6145 TAG, "Activity slept: token=" + token);
6146
6147 ActivityRecord r = null;
6148
6149 final long origId = Binder.clearCallingIdentity();
6150
6151 synchronized (this) {
6152 int index = mMainStack.indexOfTokenLocked(token);
6153 if (index >= 0) {
6154 r = (ActivityRecord)mMainStack.mHistory.get(index);
6155 mMainStack.activitySleptLocked(r);
6156 }
6157 }
6158
6159 Binder.restoreCallingIdentity(origId);
6160 }
6161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006162 public void wakingUp() {
6163 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006164 mWindowManager.setEventDispatching(true);
6165 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006166 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006167 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006168 }
6169 }
6170
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006171 public void stopAppSwitches() {
6172 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6173 != PackageManager.PERMISSION_GRANTED) {
6174 throw new SecurityException("Requires permission "
6175 + android.Manifest.permission.STOP_APP_SWITCHES);
6176 }
6177
6178 synchronized(this) {
6179 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6180 + APP_SWITCH_DELAY_TIME;
6181 mDidAppSwitch = false;
6182 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6183 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6184 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6185 }
6186 }
6187
6188 public void resumeAppSwitches() {
6189 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6190 != PackageManager.PERMISSION_GRANTED) {
6191 throw new SecurityException("Requires permission "
6192 + android.Manifest.permission.STOP_APP_SWITCHES);
6193 }
6194
6195 synchronized(this) {
6196 // Note that we don't execute any pending app switches... we will
6197 // let those wait until either the timeout, or the next start
6198 // activity request.
6199 mAppSwitchesAllowedTime = 0;
6200 }
6201 }
6202
6203 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6204 String name) {
6205 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6206 return true;
6207 }
6208
6209 final int perm = checkComponentPermission(
6210 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006211 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006212 if (perm == PackageManager.PERMISSION_GRANTED) {
6213 return true;
6214 }
6215
Joe Onorato8a9b2202010-02-26 18:56:32 -08006216 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006217 return false;
6218 }
6219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006220 public void setDebugApp(String packageName, boolean waitForDebugger,
6221 boolean persistent) {
6222 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6223 "setDebugApp()");
6224
6225 // Note that this is not really thread safe if there are multiple
6226 // callers into it at the same time, but that's not a situation we
6227 // care about.
6228 if (persistent) {
6229 final ContentResolver resolver = mContext.getContentResolver();
6230 Settings.System.putString(
6231 resolver, Settings.System.DEBUG_APP,
6232 packageName);
6233 Settings.System.putInt(
6234 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6235 waitForDebugger ? 1 : 0);
6236 }
6237
6238 synchronized (this) {
6239 if (!persistent) {
6240 mOrigDebugApp = mDebugApp;
6241 mOrigWaitForDebugger = mWaitForDebugger;
6242 }
6243 mDebugApp = packageName;
6244 mWaitForDebugger = waitForDebugger;
6245 mDebugTransient = !persistent;
6246 if (packageName != null) {
6247 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006248 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006249 Binder.restoreCallingIdentity(origId);
6250 }
6251 }
6252 }
6253
6254 public void setAlwaysFinish(boolean enabled) {
6255 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6256 "setAlwaysFinish()");
6257
6258 Settings.System.putInt(
6259 mContext.getContentResolver(),
6260 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6261
6262 synchronized (this) {
6263 mAlwaysFinishActivities = enabled;
6264 }
6265 }
6266
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006267 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006268 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006269 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006270 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006271 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006272 }
6273 }
6274
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006275 public boolean isUserAMonkey() {
6276 // For now the fact that there is a controller implies
6277 // we have a monkey.
6278 synchronized (this) {
6279 return mController != null;
6280 }
6281 }
6282
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006283 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006284 synchronized (this) {
6285 mWatchers.register(watcher);
6286 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006287 }
6288
6289 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006290 synchronized (this) {
6291 mWatchers.unregister(watcher);
6292 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006293 }
6294
Jeff Sharkeya4620792011-05-20 15:29:23 -07006295 public void registerProcessObserver(IProcessObserver observer) {
6296 mProcessObservers.register(observer);
6297 }
6298
6299 public void unregisterProcessObserver(IProcessObserver observer) {
6300 mProcessObservers.unregister(observer);
6301 }
6302
Daniel Sandler69a48172010-06-23 16:29:36 -04006303 public void setImmersive(IBinder token, boolean immersive) {
6304 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006305 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006306 if (index < 0) {
6307 throw new IllegalArgumentException();
6308 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006309 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006310 r.immersive = immersive;
6311 }
6312 }
6313
6314 public boolean isImmersive(IBinder token) {
6315 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006316 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006317 if (index < 0) {
6318 throw new IllegalArgumentException();
6319 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006320 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006321 return r.immersive;
6322 }
6323 }
6324
6325 public boolean isTopActivityImmersive() {
6326 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006327 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006328 return (r != null) ? r.immersive : false;
6329 }
6330 }
6331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006332 public final void enterSafeMode() {
6333 synchronized(this) {
6334 // It only makes sense to do this before the system is ready
6335 // and started launching other packages.
6336 if (!mSystemReady) {
6337 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006338 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006339 } catch (RemoteException e) {
6340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006341 }
6342 }
6343 }
6344
Jeff Brownb09abc12011-01-13 21:08:27 -08006345 public final void showSafeModeOverlay() {
6346 View v = LayoutInflater.from(mContext).inflate(
6347 com.android.internal.R.layout.safe_mode, null);
6348 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6349 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6350 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6351 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6352 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6353 lp.format = v.getBackground().getOpacity();
6354 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6355 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6356 ((WindowManager)mContext.getSystemService(
6357 Context.WINDOW_SERVICE)).addView(v, lp);
6358 }
6359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006360 public void noteWakeupAlarm(IIntentSender sender) {
6361 if (!(sender instanceof PendingIntentRecord)) {
6362 return;
6363 }
6364 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6365 synchronized (stats) {
6366 if (mBatteryStatsService.isOnBattery()) {
6367 mBatteryStatsService.enforceCallingPermission();
6368 PendingIntentRecord rec = (PendingIntentRecord)sender;
6369 int MY_UID = Binder.getCallingUid();
6370 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6371 BatteryStatsImpl.Uid.Pkg pkg =
6372 stats.getPackageStatsLocked(uid, rec.key.packageName);
6373 pkg.incWakeupsLocked();
6374 }
6375 }
6376 }
6377
Dianne Hackborn64825172011-03-02 21:32:58 -08006378 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006379 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006380 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006381 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006382 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006383 // XXX Note: don't acquire main activity lock here, because the window
6384 // manager calls in with its locks held.
6385
6386 boolean killed = false;
6387 synchronized (mPidsSelfLocked) {
6388 int[] types = new int[pids.length];
6389 int worstType = 0;
6390 for (int i=0; i<pids.length; i++) {
6391 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6392 if (proc != null) {
6393 int type = proc.setAdj;
6394 types[i] = type;
6395 if (type > worstType) {
6396 worstType = type;
6397 }
6398 }
6399 }
6400
Dianne Hackborn64825172011-03-02 21:32:58 -08006401 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006402 // then constrain it so we will kill all hidden procs.
6403 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6404 worstType = HIDDEN_APP_MIN_ADJ;
6405 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006406
6407 // If this is not a secure call, don't let it kill processes that
6408 // are important.
6409 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6410 worstType = SECONDARY_SERVER_ADJ;
6411 }
6412
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006413 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006414 for (int i=0; i<pids.length; i++) {
6415 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6416 if (proc == null) {
6417 continue;
6418 }
6419 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006420 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006421 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006422 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6423 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006424 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006425 proc.killedBackground = true;
6426 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006427 }
6428 }
6429 }
6430 return killed;
6431 }
6432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006433 public final void startRunning(String pkg, String cls, String action,
6434 String data) {
6435 synchronized(this) {
6436 if (mStartRunning) {
6437 return;
6438 }
6439 mStartRunning = true;
6440 mTopComponent = pkg != null && cls != null
6441 ? new ComponentName(pkg, cls) : null;
6442 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6443 mTopData = data;
6444 if (!mSystemReady) {
6445 return;
6446 }
6447 }
6448
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006449 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006450 }
6451
6452 private void retrieveSettings() {
6453 final ContentResolver resolver = mContext.getContentResolver();
6454 String debugApp = Settings.System.getString(
6455 resolver, Settings.System.DEBUG_APP);
6456 boolean waitForDebugger = Settings.System.getInt(
6457 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6458 boolean alwaysFinishActivities = Settings.System.getInt(
6459 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6460
6461 Configuration configuration = new Configuration();
6462 Settings.System.getConfiguration(resolver, configuration);
6463
6464 synchronized (this) {
6465 mDebugApp = mOrigDebugApp = debugApp;
6466 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6467 mAlwaysFinishActivities = alwaysFinishActivities;
6468 // This happens before any activities are started, so we can
6469 // change mConfiguration in-place.
6470 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006471 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006472 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006473 }
6474 }
6475
6476 public boolean testIsSystemReady() {
6477 // no need to synchronize(this) just to read & return the value
6478 return mSystemReady;
6479 }
6480
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006481 private static File getCalledPreBootReceiversFile() {
6482 File dataDir = Environment.getDataDirectory();
6483 File systemDir = new File(dataDir, "system");
6484 File fname = new File(systemDir, "called_pre_boots.dat");
6485 return fname;
6486 }
6487
6488 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6489 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6490 File file = getCalledPreBootReceiversFile();
6491 FileInputStream fis = null;
6492 try {
6493 fis = new FileInputStream(file);
6494 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6495 int vers = dis.readInt();
6496 String codename = dis.readUTF();
6497 if (vers == android.os.Build.VERSION.SDK_INT
6498 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6499 int num = dis.readInt();
6500 while (num > 0) {
6501 num--;
6502 String pkg = dis.readUTF();
6503 String cls = dis.readUTF();
6504 lastDoneReceivers.add(new ComponentName(pkg, cls));
6505 }
6506 }
6507 } catch (FileNotFoundException e) {
6508 } catch (IOException e) {
6509 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6510 } finally {
6511 if (fis != null) {
6512 try {
6513 fis.close();
6514 } catch (IOException e) {
6515 }
6516 }
6517 }
6518 return lastDoneReceivers;
6519 }
6520
6521 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6522 File file = getCalledPreBootReceiversFile();
6523 FileOutputStream fos = null;
6524 DataOutputStream dos = null;
6525 try {
6526 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6527 fos = new FileOutputStream(file);
6528 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6529 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6530 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6531 dos.writeInt(list.size());
6532 for (int i=0; i<list.size(); i++) {
6533 dos.writeUTF(list.get(i).getPackageName());
6534 dos.writeUTF(list.get(i).getClassName());
6535 }
6536 } catch (IOException e) {
6537 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6538 file.delete();
6539 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006540 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006541 if (dos != null) {
6542 try {
6543 dos.close();
6544 } catch (IOException e) {
6545 // TODO Auto-generated catch block
6546 e.printStackTrace();
6547 }
6548 }
6549 }
6550 }
6551
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006552 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006553 // In the simulator, startRunning will never have been called, which
6554 // normally sets a few crucial variables. Do it here instead.
6555 if (!Process.supportsProcesses()) {
6556 mStartRunning = true;
6557 mTopAction = Intent.ACTION_MAIN;
6558 }
6559
6560 synchronized(this) {
6561 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006562 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006563 return;
6564 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006565
6566 // Check to see if there are any update receivers to run.
6567 if (!mDidUpdate) {
6568 if (mWaitingUpdate) {
6569 return;
6570 }
6571 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6572 List<ResolveInfo> ris = null;
6573 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006574 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006575 intent, null, 0);
6576 } catch (RemoteException e) {
6577 }
6578 if (ris != null) {
6579 for (int i=ris.size()-1; i>=0; i--) {
6580 if ((ris.get(i).activityInfo.applicationInfo.flags
6581 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6582 ris.remove(i);
6583 }
6584 }
6585 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006586
6587 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6588
6589 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006590 for (int i=0; i<ris.size(); i++) {
6591 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006592 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6593 if (lastDoneReceivers.contains(comp)) {
6594 ris.remove(i);
6595 i--;
6596 }
6597 }
6598
6599 for (int i=0; i<ris.size(); i++) {
6600 ActivityInfo ai = ris.get(i).activityInfo;
6601 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6602 doneReceivers.add(comp);
6603 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006604 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006605 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006606 finisher = new IIntentReceiver.Stub() {
6607 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006608 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006609 boolean sticky) {
6610 // The raw IIntentReceiver interface is called
6611 // with the AM lock held, so redispatch to
6612 // execute our code without the lock.
6613 mHandler.post(new Runnable() {
6614 public void run() {
6615 synchronized (ActivityManagerService.this) {
6616 mDidUpdate = true;
6617 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006618 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006619 systemReady(goingCallback);
6620 }
6621 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006622 }
6623 };
6624 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006625 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006626 broadcastIntentLocked(null, null, intent, null, finisher,
6627 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006628 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006629 mWaitingUpdate = true;
6630 }
6631 }
6632 }
6633 if (mWaitingUpdate) {
6634 return;
6635 }
6636 mDidUpdate = true;
6637 }
6638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006639 mSystemReady = true;
6640 if (!mStartRunning) {
6641 return;
6642 }
6643 }
6644
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006645 ArrayList<ProcessRecord> procsToKill = null;
6646 synchronized(mPidsSelfLocked) {
6647 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6648 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6649 if (!isAllowedWhileBooting(proc.info)){
6650 if (procsToKill == null) {
6651 procsToKill = new ArrayList<ProcessRecord>();
6652 }
6653 procsToKill.add(proc);
6654 }
6655 }
6656 }
6657
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006658 synchronized(this) {
6659 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006660 for (int i=procsToKill.size()-1; i>=0; i--) {
6661 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006662 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006663 removeProcessLocked(proc, true);
6664 }
6665 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006666
6667 // Now that we have cleaned up any update processes, we
6668 // are ready to start launching real processes and know that
6669 // we won't trample on them any more.
6670 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006671 }
6672
Joe Onorato8a9b2202010-02-26 18:56:32 -08006673 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006674 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006675 SystemClock.uptimeMillis());
6676
6677 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006678 // Make sure we have no pre-ready processes sitting around.
6679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006680 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6681 ResolveInfo ri = mContext.getPackageManager()
6682 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006683 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006684 CharSequence errorMsg = null;
6685 if (ri != null) {
6686 ActivityInfo ai = ri.activityInfo;
6687 ApplicationInfo app = ai.applicationInfo;
6688 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6689 mTopAction = Intent.ACTION_FACTORY_TEST;
6690 mTopData = null;
6691 mTopComponent = new ComponentName(app.packageName,
6692 ai.name);
6693 } else {
6694 errorMsg = mContext.getResources().getText(
6695 com.android.internal.R.string.factorytest_not_system);
6696 }
6697 } else {
6698 errorMsg = mContext.getResources().getText(
6699 com.android.internal.R.string.factorytest_no_action);
6700 }
6701 if (errorMsg != null) {
6702 mTopAction = null;
6703 mTopData = null;
6704 mTopComponent = null;
6705 Message msg = Message.obtain();
6706 msg.what = SHOW_FACTORY_ERROR_MSG;
6707 msg.getData().putCharSequence("msg", errorMsg);
6708 mHandler.sendMessage(msg);
6709 }
6710 }
6711 }
6712
6713 retrieveSettings();
6714
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006715 if (goingCallback != null) goingCallback.run();
6716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006717 synchronized (this) {
6718 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6719 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006720 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006721 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006722 if (apps != null) {
6723 int N = apps.size();
6724 int i;
6725 for (i=0; i<N; i++) {
6726 ApplicationInfo info
6727 = (ApplicationInfo)apps.get(i);
6728 if (info != null &&
6729 !info.packageName.equals("android")) {
6730 addAppLocked(info);
6731 }
6732 }
6733 }
6734 } catch (RemoteException ex) {
6735 // pm is in same process, this will never happen.
6736 }
6737 }
6738
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006739 // Start up initial activity.
6740 mBooting = true;
6741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006742 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006743 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006744 Message msg = Message.obtain();
6745 msg.what = SHOW_UID_ERROR_MSG;
6746 mHandler.sendMessage(msg);
6747 }
6748 } catch (RemoteException e) {
6749 }
6750
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006751 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006752 }
6753 }
6754
Dan Egnorb7f03672009-12-09 16:22:32 -08006755 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006756 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006757 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006758 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006759 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006760 startAppProblemLocked(app);
6761 app.stopFreezingAllLocked();
6762 return handleAppCrashLocked(app);
6763 }
6764
Dan Egnorb7f03672009-12-09 16:22:32 -08006765 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006766 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006767 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006768 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006769 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6770 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006771 startAppProblemLocked(app);
6772 app.stopFreezingAllLocked();
6773 }
6774
6775 /**
6776 * Generate a process error record, suitable for attachment to a ProcessRecord.
6777 *
6778 * @param app The ProcessRecord in which the error occurred.
6779 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6780 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006781 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006782 * @param shortMsg Short message describing the crash.
6783 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006784 * @param stackTrace Full crash stack trace, may be null.
6785 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006786 * @return Returns a fully-formed AppErrorStateInfo record.
6787 */
6788 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006789 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006790 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006792 report.condition = condition;
6793 report.processName = app.processName;
6794 report.pid = app.pid;
6795 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006796 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006797 report.shortMsg = shortMsg;
6798 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006799 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006800
6801 return report;
6802 }
6803
Dan Egnor42471dd2010-01-07 17:25:22 -08006804 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006805 synchronized (this) {
6806 app.crashing = false;
6807 app.crashingReport = null;
6808 app.notResponding = false;
6809 app.notRespondingReport = null;
6810 if (app.anrDialog == fromDialog) {
6811 app.anrDialog = null;
6812 }
6813 if (app.waitDialog == fromDialog) {
6814 app.waitDialog = null;
6815 }
6816 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006817 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006818 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07006819 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6820 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006821 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006823 }
6824 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006825
Dan Egnorb7f03672009-12-09 16:22:32 -08006826 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006827 long now = SystemClock.uptimeMillis();
6828
6829 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6830 app.info.uid);
6831 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6832 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006833 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006834 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006835 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006836 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006837 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6838 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006839 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006840 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006841 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006842 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006843 }
6844 }
6845 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006846 // Don't let services in this process be restarted and potentially
6847 // annoy the user repeatedly. Unless it is persistent, since those
6848 // processes run critical code.
6849 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006850 // We don't want to start this process again until the user
6851 // explicitly does so... but for persistent process, we really
6852 // need to keep it running. If a persistent process is actually
6853 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006854 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006855 app.info.processName);
6856 mBadProcesses.put(app.info.processName, app.info.uid, now);
6857 app.bad = true;
6858 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6859 app.removed = true;
6860 removeProcessLocked(app, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006861 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006862 return false;
6863 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006864 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006865 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006866 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006867 if (r.app == app) {
6868 // If the top running activity is from this crashing
6869 // process, then terminate it to avoid getting in a loop.
6870 Slog.w(TAG, " Force finishing activity "
6871 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006872 int index = mMainStack.indexOfTokenLocked(r);
6873 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006874 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006875 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006876 // stopped, to avoid a situation where one will get
6877 // re-start our crashing activity once it gets resumed again.
6878 index--;
6879 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006880 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006881 if (r.state == ActivityState.RESUMED
6882 || r.state == ActivityState.PAUSING
6883 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006884 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006885 Slog.w(TAG, " Force finishing activity "
6886 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006887 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006888 Activity.RESULT_CANCELED, null, "crashed");
6889 }
6890 }
6891 }
6892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006893 }
6894
6895 // Bump up the crash count of any services currently running in the proc.
6896 if (app.services.size() != 0) {
6897 // Any services running in the application need to be placed
6898 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006899 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006901 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006902 sr.crashCount++;
6903 }
6904 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006905
6906 // If the crashing process is what we consider to be the "home process" and it has been
6907 // replaced by a third-party app, clear the package preferred activities from packages
6908 // with a home activity running in the process to prevent a repeatedly crashing app
6909 // from blocking the user to manually clear the list.
6910 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6911 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6912 Iterator it = mHomeProcess.activities.iterator();
6913 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006914 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006915 if (r.isHomeActivity) {
6916 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6917 try {
6918 ActivityThread.getPackageManager()
6919 .clearPackagePreferredActivities(r.packageName);
6920 } catch (RemoteException c) {
6921 // pm is in same process, this will never happen.
6922 }
6923 }
6924 }
6925 }
6926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006927 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6928 return true;
6929 }
6930
6931 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006932 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6933 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006934 skipCurrentReceiverLocked(app);
6935 }
6936
6937 void skipCurrentReceiverLocked(ProcessRecord app) {
6938 boolean reschedule = false;
6939 BroadcastRecord r = app.curReceiver;
6940 if (r != null) {
6941 // The current broadcast is waiting for this app's receiver
6942 // to be finished. Looks like that's not going to happen, so
6943 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006944 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006945 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6946 r.resultExtras, r.resultAbort, true);
6947 reschedule = true;
6948 }
6949 r = mPendingBroadcast;
6950 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006951 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006952 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006953 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006954 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6955 r.resultExtras, r.resultAbort, true);
6956 reschedule = true;
6957 }
6958 if (reschedule) {
6959 scheduleBroadcastsLocked();
6960 }
6961 }
6962
Dan Egnor60d87622009-12-16 16:32:58 -08006963 /**
6964 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6965 * The application process will exit immediately after this call returns.
6966 * @param app object of the crashing app, null for the system server
6967 * @param crashInfo describing the exception
6968 */
6969 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006970 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08006971
6972 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6973 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006974 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006975 crashInfo.exceptionClassName,
6976 crashInfo.exceptionMessage,
6977 crashInfo.throwFileName,
6978 crashInfo.throwLineNumber);
6979
Dan Egnor42471dd2010-01-07 17:25:22 -08006980 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006981
6982 crashApplication(r, crashInfo);
6983 }
6984
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006985 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006986 IBinder app,
6987 int violationMask,
6988 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006989 ProcessRecord r = findAppProcess(app, "StrictMode");
6990 if (r == null) {
6991 return;
6992 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006993
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006994 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006995 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006996 boolean logIt = true;
6997 synchronized (mAlreadyLoggedViolatedStacks) {
6998 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6999 logIt = false;
7000 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007001 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007002 // the relative pain numbers, without logging all
7003 // the stack traces repeatedly. We'd want to do
7004 // likewise in the client code, which also does
7005 // dup suppression, before the Binder call.
7006 } else {
7007 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
7008 mAlreadyLoggedViolatedStacks.clear();
7009 }
7010 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
7011 }
7012 }
7013 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007014 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007015 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007016 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007017
7018 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
7019 AppErrorResult result = new AppErrorResult();
7020 synchronized (this) {
7021 final long origId = Binder.clearCallingIdentity();
7022
7023 Message msg = Message.obtain();
7024 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7025 HashMap<String, Object> data = new HashMap<String, Object>();
7026 data.put("result", result);
7027 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007028 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007029 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007030 msg.obj = data;
7031 mHandler.sendMessage(msg);
7032
7033 Binder.restoreCallingIdentity(origId);
7034 }
7035 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007036 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007037 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007038 }
7039
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007040 // Depending on the policy in effect, there could be a bunch of
7041 // these in quick succession so we try to batch these together to
7042 // minimize disk writes, number of dropbox entries, and maximize
7043 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007044 private void logStrictModeViolationToDropBox(
7045 ProcessRecord process,
7046 StrictMode.ViolationInfo info) {
7047 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007048 return;
7049 }
7050 final boolean isSystemApp = process == null ||
7051 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7052 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
7053 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7054 final DropBoxManager dbox = (DropBoxManager)
7055 mContext.getSystemService(Context.DROPBOX_SERVICE);
7056
7057 // Exit early if the dropbox isn't configured to accept this report type.
7058 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7059
7060 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007061 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007062 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7063 synchronized (sb) {
7064 bufferWasEmpty = sb.length() == 0;
7065 appendDropBoxProcessHeaders(process, sb);
7066 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7067 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007068 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7069 if (info.violationNumThisLoop != 0) {
7070 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7071 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007072 if (info.numAnimationsRunning != 0) {
7073 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7074 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007075 if (info.broadcastIntentAction != null) {
7076 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7077 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007078 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007079 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007080 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007081 if (info.numInstances != -1) {
7082 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7083 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007084 if (info.tags != null) {
7085 for (String tag : info.tags) {
7086 sb.append("Span-Tag: ").append(tag).append("\n");
7087 }
7088 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007089 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007090 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7091 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007092 }
7093 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007094
7095 // Only buffer up to ~64k. Various logging bits truncate
7096 // things at 128k.
7097 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007098 }
7099
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007100 // Flush immediately if the buffer's grown too large, or this
7101 // is a non-system app. Non-system apps are isolated with a
7102 // different tag & policy and not batched.
7103 //
7104 // Batching is useful during internal testing with
7105 // StrictMode settings turned up high. Without batching,
7106 // thousands of separate files could be created on boot.
7107 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007108 new Thread("Error dump: " + dropboxTag) {
7109 @Override
7110 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007111 String report;
7112 synchronized (sb) {
7113 report = sb.toString();
7114 sb.delete(0, sb.length());
7115 sb.trimToSize();
7116 }
7117 if (report.length() != 0) {
7118 dbox.addText(dropboxTag, report);
7119 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007120 }
7121 }.start();
7122 return;
7123 }
7124
7125 // System app batching:
7126 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007127 // An existing dropbox-writing thread is outstanding, so
7128 // we don't need to start it up. The existing thread will
7129 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007130 return;
7131 }
7132
7133 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7134 // (After this point, we shouldn't access AMS internal data structures.)
7135 new Thread("Error dump: " + dropboxTag) {
7136 @Override
7137 public void run() {
7138 // 5 second sleep to let stacks arrive and be batched together
7139 try {
7140 Thread.sleep(5000); // 5 seconds
7141 } catch (InterruptedException e) {}
7142
7143 String errorReport;
7144 synchronized (mStrictModeBuffer) {
7145 errorReport = mStrictModeBuffer.toString();
7146 if (errorReport.length() == 0) {
7147 return;
7148 }
7149 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7150 mStrictModeBuffer.trimToSize();
7151 }
7152 dbox.addText(dropboxTag, errorReport);
7153 }
7154 }.start();
7155 }
7156
Dan Egnor60d87622009-12-16 16:32:58 -08007157 /**
7158 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7159 * @param app object of the crashing app, null for the system server
7160 * @param tag reported by the caller
7161 * @param crashInfo describing the context of the error
7162 * @return true if the process should exit immediately (WTF is fatal)
7163 */
7164 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007165 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007166 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007167
7168 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7169 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007170 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007171 tag, crashInfo.exceptionMessage);
7172
Dan Egnor42471dd2010-01-07 17:25:22 -08007173 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007174
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007175 if (r != null && r.pid != Process.myPid() &&
7176 Settings.Secure.getInt(mContext.getContentResolver(),
7177 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007178 crashApplication(r, crashInfo);
7179 return true;
7180 } else {
7181 return false;
7182 }
7183 }
7184
7185 /**
7186 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7187 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7188 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007189 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007190 if (app == null) {
7191 return null;
7192 }
7193
7194 synchronized (this) {
7195 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7196 final int NA = apps.size();
7197 for (int ia=0; ia<NA; ia++) {
7198 ProcessRecord p = apps.valueAt(ia);
7199 if (p.thread != null && p.thread.asBinder() == app) {
7200 return p;
7201 }
7202 }
7203 }
7204
Dianne Hackborncb44d962011-03-10 17:02:27 -08007205 Slog.w(TAG, "Can't find mystery application for " + reason
7206 + " from pid=" + Binder.getCallingPid()
7207 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007208 return null;
7209 }
7210 }
7211
7212 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007213 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7214 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007215 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007216 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007217 // Watchdog thread ends up invoking this function (with
7218 // a null ProcessRecord) to add the stack file to dropbox.
7219 // Do not acquire a lock on this (am) in such cases, as it
7220 // could cause a potential deadlock, if and when watchdog
7221 // is invoked due to unavailability of lock on am and it
7222 // would prevent watchdog from killing system_server.
7223 if (process == null) {
7224 sb.append("Process: system_server\n");
7225 return;
7226 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007227 // Note: ProcessRecord 'process' is guarded by the service
7228 // instance. (notably process.pkgList, which could otherwise change
7229 // concurrently during execution of this method)
7230 synchronized (this) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007231 if (process.pid == MY_PID) {
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007232 sb.append("Process: system_server\n");
7233 } else {
7234 sb.append("Process: ").append(process.processName).append("\n");
7235 }
Dan Egnora455d192010-03-12 08:52:28 -08007236 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007237 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007238 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7239 for (String pkg : process.pkgList) {
7240 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007241 try {
Dan Egnora455d192010-03-12 08:52:28 -08007242 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7243 if (pi != null) {
7244 sb.append(" v").append(pi.versionCode);
7245 if (pi.versionName != null) {
7246 sb.append(" (").append(pi.versionName).append(")");
7247 }
7248 }
7249 } catch (RemoteException e) {
7250 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007251 }
Dan Egnora455d192010-03-12 08:52:28 -08007252 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007253 }
Dan Egnora455d192010-03-12 08:52:28 -08007254 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007255 }
7256
7257 private static String processClass(ProcessRecord process) {
7258 if (process == null || process.pid == MY_PID) {
7259 return "system_server";
7260 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7261 return "system_app";
7262 } else {
7263 return "data_app";
7264 }
7265 }
7266
7267 /**
7268 * Write a description of an error (crash, WTF, ANR) to the drop box.
7269 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7270 * @param process which caused the error, null means the system server
7271 * @param activity which triggered the error, null if unknown
7272 * @param parent activity related to the error, null if unknown
7273 * @param subject line related to the error, null if absent
7274 * @param report in long form describing the error, null if absent
7275 * @param logFile to include in the report, null if none
7276 * @param crashInfo giving an application stack trace, null if absent
7277 */
7278 public void addErrorToDropBox(String eventType,
7279 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7280 final String report, final File logFile,
7281 final ApplicationErrorReport.CrashInfo crashInfo) {
7282 // NOTE -- this must never acquire the ActivityManagerService lock,
7283 // otherwise the watchdog may be prevented from resetting the system.
7284
7285 final String dropboxTag = processClass(process) + "_" + eventType;
7286 final DropBoxManager dbox = (DropBoxManager)
7287 mContext.getSystemService(Context.DROPBOX_SERVICE);
7288
7289 // Exit early if the dropbox isn't configured to accept this report type.
7290 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7291
7292 final StringBuilder sb = new StringBuilder(1024);
7293 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007294 if (activity != null) {
7295 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7296 }
7297 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7298 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7299 }
7300 if (parent != null && parent != activity) {
7301 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7302 }
7303 if (subject != null) {
7304 sb.append("Subject: ").append(subject).append("\n");
7305 }
7306 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007307 if (Debug.isDebuggerConnected()) {
7308 sb.append("Debugger: Connected\n");
7309 }
Dan Egnora455d192010-03-12 08:52:28 -08007310 sb.append("\n");
7311
7312 // Do the rest in a worker thread to avoid blocking the caller on I/O
7313 // (After this point, we shouldn't access AMS internal data structures.)
7314 Thread worker = new Thread("Error dump: " + dropboxTag) {
7315 @Override
7316 public void run() {
7317 if (report != null) {
7318 sb.append(report);
7319 }
7320 if (logFile != null) {
7321 try {
7322 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7323 } catch (IOException e) {
7324 Slog.e(TAG, "Error reading " + logFile, e);
7325 }
7326 }
7327 if (crashInfo != null && crashInfo.stackTrace != null) {
7328 sb.append(crashInfo.stackTrace);
7329 }
7330
7331 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7332 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7333 if (lines > 0) {
7334 sb.append("\n");
7335
7336 // Merge several logcat streams, and take the last N lines
7337 InputStreamReader input = null;
7338 try {
7339 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7340 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7341 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7342
7343 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7344 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7345 input = new InputStreamReader(logcat.getInputStream());
7346
7347 int num;
7348 char[] buf = new char[8192];
7349 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7350 } catch (IOException e) {
7351 Slog.e(TAG, "Error running logcat", e);
7352 } finally {
7353 if (input != null) try { input.close(); } catch (IOException e) {}
7354 }
7355 }
7356
7357 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007358 }
Dan Egnora455d192010-03-12 08:52:28 -08007359 };
7360
7361 if (process == null || process.pid == MY_PID) {
7362 worker.run(); // We may be about to die -- need to run this synchronously
7363 } else {
7364 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007365 }
7366 }
7367
7368 /**
7369 * Bring up the "unexpected error" dialog box for a crashing app.
7370 * Deal with edge cases (intercepts from instrumented applications,
7371 * ActivityController, error intent receivers, that sort of thing).
7372 * @param r the application crashing
7373 * @param crashInfo describing the failure
7374 */
7375 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007376 long timeMillis = System.currentTimeMillis();
7377 String shortMsg = crashInfo.exceptionClassName;
7378 String longMsg = crashInfo.exceptionMessage;
7379 String stackTrace = crashInfo.stackTrace;
7380 if (shortMsg != null && longMsg != null) {
7381 longMsg = shortMsg + ": " + longMsg;
7382 } else if (shortMsg != null) {
7383 longMsg = shortMsg;
7384 }
7385
Dan Egnor60d87622009-12-16 16:32:58 -08007386 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007387 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007388 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007389 try {
7390 String name = r != null ? r.processName : null;
7391 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007392 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007393 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007394 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007395 + " at watcher's request");
7396 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007397 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398 }
7399 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007400 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 }
7402 }
7403
7404 final long origId = Binder.clearCallingIdentity();
7405
7406 // If this process is running instrumentation, finish it.
7407 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007408 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007409 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007410 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7411 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007412 Bundle info = new Bundle();
7413 info.putString("shortMsg", shortMsg);
7414 info.putString("longMsg", longMsg);
7415 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7416 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007417 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007418 }
7419
Dan Egnor60d87622009-12-16 16:32:58 -08007420 // If we can't identify the process or it's already exceeded its crash quota,
7421 // quit right away without showing a crash dialog.
7422 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007424 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007425 }
7426
7427 Message msg = Message.obtain();
7428 msg.what = SHOW_ERROR_MSG;
7429 HashMap data = new HashMap();
7430 data.put("result", result);
7431 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007432 msg.obj = data;
7433 mHandler.sendMessage(msg);
7434
7435 Binder.restoreCallingIdentity(origId);
7436 }
7437
7438 int res = result.get();
7439
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007440 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007441 synchronized (this) {
7442 if (r != null) {
7443 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7444 SystemClock.uptimeMillis());
7445 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007446 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007447 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007448 }
7449 }
7450
7451 if (appErrorIntent != null) {
7452 try {
7453 mContext.startActivity(appErrorIntent);
7454 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007455 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007458 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007459
7460 Intent createAppErrorIntentLocked(ProcessRecord r,
7461 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7462 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007463 if (report == null) {
7464 return null;
7465 }
7466 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7467 result.setComponent(r.errorReportReceiver);
7468 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7469 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7470 return result;
7471 }
7472
Dan Egnorb7f03672009-12-09 16:22:32 -08007473 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7474 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007475 if (r.errorReportReceiver == null) {
7476 return null;
7477 }
7478
7479 if (!r.crashing && !r.notResponding) {
7480 return null;
7481 }
7482
Dan Egnorb7f03672009-12-09 16:22:32 -08007483 ApplicationErrorReport report = new ApplicationErrorReport();
7484 report.packageName = r.info.packageName;
7485 report.installerPackageName = r.errorReportReceiver.getPackageName();
7486 report.processName = r.processName;
7487 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007488 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007489
Dan Egnorb7f03672009-12-09 16:22:32 -08007490 if (r.crashing) {
7491 report.type = ApplicationErrorReport.TYPE_CRASH;
7492 report.crashInfo = crashInfo;
7493 } else if (r.notResponding) {
7494 report.type = ApplicationErrorReport.TYPE_ANR;
7495 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007496
Dan Egnorb7f03672009-12-09 16:22:32 -08007497 report.anrInfo.activity = r.notRespondingReport.tag;
7498 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7499 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007500 }
7501
Dan Egnorb7f03672009-12-09 16:22:32 -08007502 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007503 }
7504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007505 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7506 // assume our apps are happy - lazy create the list
7507 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7508
7509 synchronized (this) {
7510
7511 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007512 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7513 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007514 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7515 // This one's in trouble, so we'll generate a report for it
7516 // crashes are higher priority (in case there's a crash *and* an anr)
7517 ActivityManager.ProcessErrorStateInfo report = null;
7518 if (app.crashing) {
7519 report = app.crashingReport;
7520 } else if (app.notResponding) {
7521 report = app.notRespondingReport;
7522 }
7523
7524 if (report != null) {
7525 if (errList == null) {
7526 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7527 }
7528 errList.add(report);
7529 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007530 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007531 " crashing = " + app.crashing +
7532 " notResponding = " + app.notResponding);
7533 }
7534 }
7535 }
7536 }
7537
7538 return errList;
7539 }
7540
7541 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7542 // Lazy instantiation of list
7543 List<ActivityManager.RunningAppProcessInfo> runList = null;
7544 synchronized (this) {
7545 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007546 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7547 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007548 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7549 // Generate process state info for running application
7550 ActivityManager.RunningAppProcessInfo currApp =
7551 new ActivityManager.RunningAppProcessInfo(app.processName,
7552 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007553 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007554 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007555 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007556 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007557 if (app.persistent) {
7558 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007560 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007561 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007562 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7563 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7564 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007565 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7566 } else if (adj >= HOME_APP_ADJ) {
7567 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7568 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569 } else if (adj >= SECONDARY_SERVER_ADJ) {
7570 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007571 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007572 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007573 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7574 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007575 } else if (adj >= VISIBLE_APP_ADJ) {
7576 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7577 } else {
7578 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7579 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007580 currApp.importanceReasonCode = app.adjTypeCode;
7581 if (app.adjSource instanceof ProcessRecord) {
7582 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007583 } else if (app.adjSource instanceof ActivityRecord) {
7584 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007585 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7586 }
7587 if (app.adjTarget instanceof ComponentName) {
7588 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7589 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007590 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 // + " lru=" + currApp.lru);
7592 if (runList == null) {
7593 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7594 }
7595 runList.add(currApp);
7596 }
7597 }
7598 }
7599 return runList;
7600 }
7601
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007602 public List<ApplicationInfo> getRunningExternalApplications() {
7603 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7604 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7605 if (runningApps != null && runningApps.size() > 0) {
7606 Set<String> extList = new HashSet<String>();
7607 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7608 if (app.pkgList != null) {
7609 for (String pkg : app.pkgList) {
7610 extList.add(pkg);
7611 }
7612 }
7613 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007614 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007615 for (String pkg : extList) {
7616 try {
7617 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7618 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7619 retList.add(info);
7620 }
7621 } catch (RemoteException e) {
7622 }
7623 }
7624 }
7625 return retList;
7626 }
7627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007628 @Override
7629 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007630 if (checkCallingPermission(android.Manifest.permission.DUMP)
7631 != PackageManager.PERMISSION_GRANTED) {
7632 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7633 + Binder.getCallingPid()
7634 + ", uid=" + Binder.getCallingUid()
7635 + " without permission "
7636 + android.Manifest.permission.DUMP);
7637 return;
7638 }
7639
7640 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007641 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007642
7643 int opti = 0;
7644 while (opti < args.length) {
7645 String opt = args[opti];
7646 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7647 break;
7648 }
7649 opti++;
7650 if ("-a".equals(opt)) {
7651 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007652 } else if ("-c".equals(opt)) {
7653 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007654 } else if ("-h".equals(opt)) {
7655 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007656 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007657 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007658 pw.println(" a[ctivities]: activity stack state");
7659 pw.println(" b[roadcasts]: broadcast state");
7660 pw.println(" i[ntents]: pending intent state");
7661 pw.println(" p[rocesses]: process state");
7662 pw.println(" o[om]: out of memory management");
7663 pw.println(" prov[iders]: content provider state");
7664 pw.println(" s[ervices]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007665 pw.println(" service [COMP_SPEC]: service client-side state");
7666 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
7667 pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),");
7668 pw.println(" a partial substring in a component name, an");
7669 pw.println(" ActivityRecord hex object identifier, or");
7670 pw.println(" \"all\" for all objects");
7671 pw.println(" -a: include all available server state.");
7672 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007674 } else {
7675 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007676 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007677 }
7678
7679 // Is the caller requesting to dump a particular piece of data?
7680 if (opti < args.length) {
7681 String cmd = args[opti];
7682 opti++;
7683 if ("activities".equals(cmd) || "a".equals(cmd)) {
7684 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007685 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007686 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007687 return;
7688 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7689 synchronized (this) {
7690 dumpBroadcastsLocked(fd, pw, args, opti, true);
7691 }
7692 return;
7693 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7694 synchronized (this) {
7695 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7696 }
7697 return;
7698 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7699 synchronized (this) {
7700 dumpProcessesLocked(fd, pw, args, opti, true);
7701 }
7702 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007703 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7704 synchronized (this) {
7705 dumpOomLocked(fd, pw, args, opti, true);
7706 }
7707 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007708 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7709 synchronized (this) {
7710 dumpProvidersLocked(fd, pw, args, opti, true);
7711 }
7712 return;
7713 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007714 String[] newArgs;
7715 String name;
7716 if (opti >= args.length) {
7717 name = null;
7718 newArgs = EMPTY_STRING_ARRAY;
7719 } else {
7720 name = args[opti];
7721 opti++;
7722 newArgs = new String[args.length - opti];
7723 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7724 }
7725 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7726 pw.println("No services match: " + name);
7727 pw.println("Use -h for help.");
7728 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007729 return;
7730 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7731 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007732 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007733 }
7734 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007735 } else {
7736 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007737 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7738 pw.println("Bad activity command, or no activities match: " + cmd);
7739 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007740 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007741 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007742 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007743 }
7744
7745 // No piece of data specified, dump everything.
7746 synchronized (this) {
7747 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007748 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007749 if (needSep) {
7750 pw.println(" ");
7751 }
7752 if (dumpAll) {
7753 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007754 }
7755 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7756 if (needSep) {
7757 pw.println(" ");
7758 }
7759 if (dumpAll) {
7760 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007761 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007762 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007763 if (needSep) {
7764 pw.println(" ");
7765 }
7766 if (dumpAll) {
7767 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007768 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007769 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007770 if (needSep) {
7771 pw.println(" ");
7772 }
7773 if (dumpAll) {
7774 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007775 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007776 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007777 if (needSep) {
7778 pw.println(" ");
7779 }
7780 if (dumpAll) {
7781 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007782 }
7783 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7784 }
7785 }
7786
7787 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007788 int opti, boolean dumpAll, boolean dumpClient) {
7789 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7790 pw.println(" Main stack:");
7791 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007792 pw.println(" ");
7793 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007794 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007795 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007796 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007797 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007798 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7799 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007800 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007801 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007802 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007803 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007804 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7805 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007806 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007807 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7808 pw.println(" ");
7809 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007810 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7811 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007812 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007813 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007814 pw.println(" ");
7815 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007816 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7817 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007819
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007820 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007821 if (mMainStack.mPausingActivity != null) {
7822 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7823 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007824 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007825 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007826 if (dumpAll) {
7827 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7828 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
7829 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007830
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007831 if (mRecentTasks.size() > 0) {
7832 pw.println();
7833 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007834
7835 final int N = mRecentTasks.size();
7836 for (int i=0; i<N; i++) {
7837 TaskRecord tr = mRecentTasks.get(i);
7838 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7839 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007840 if (dumpAll) {
7841 mRecentTasks.get(i).dump(pw, " ");
7842 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007843 }
7844 }
7845
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007846 if (dumpAll) {
7847 pw.println(" ");
7848 pw.println(" mCurTask: " + mCurTask);
7849 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007850
7851 return true;
7852 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007853
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007854 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7855 int opti, boolean dumpAll) {
7856 boolean needSep = false;
7857 int numPers = 0;
7858
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007859 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7860
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007861 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7863 final int NA = procs.size();
7864 for (int ia=0; ia<NA; ia++) {
7865 if (!needSep) {
7866 pw.println(" All known processes:");
7867 needSep = true;
7868 }
7869 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007870 pw.print(r.persistent ? " *PERS*" : " *APP*");
7871 pw.print(" UID "); pw.print(procs.keyAt(ia));
7872 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007873 r.dump(pw, " ");
7874 if (r.persistent) {
7875 numPers++;
7876 }
7877 }
7878 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007879 }
7880
7881 if (mLruProcesses.size() > 0) {
7882 if (needSep) pw.println(" ");
7883 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007884 pw.println(" Process LRU list (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007885 dumpProcessOomList(pw, this, mLruProcesses, " ",
7886 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007887 needSep = true;
7888 }
7889
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007890 if (dumpAll) {
7891 synchronized (mPidsSelfLocked) {
7892 if (mPidsSelfLocked.size() > 0) {
7893 if (needSep) pw.println(" ");
7894 needSep = true;
7895 pw.println(" PID mappings:");
7896 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7897 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7898 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
7899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900 }
7901 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007902 }
7903
7904 if (mForegroundProcesses.size() > 0) {
7905 if (needSep) pw.println(" ");
7906 needSep = true;
7907 pw.println(" Foreground Processes:");
7908 for (int i=0; i<mForegroundProcesses.size(); i++) {
7909 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7910 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007912 }
7913
7914 if (mPersistentStartingProcesses.size() > 0) {
7915 if (needSep) pw.println(" ");
7916 needSep = true;
7917 pw.println(" Persisent processes that are starting:");
7918 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007919 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007921
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007922 if (mStartingProcesses.size() > 0) {
7923 if (needSep) pw.println(" ");
7924 needSep = true;
7925 pw.println(" Processes that are starting:");
7926 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007927 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007928 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007929
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007930 if (mRemovedProcesses.size() > 0) {
7931 if (needSep) pw.println(" ");
7932 needSep = true;
7933 pw.println(" Processes that are being removed:");
7934 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007935 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007936 }
7937
7938 if (mProcessesOnHold.size() > 0) {
7939 if (needSep) pw.println(" ");
7940 needSep = true;
7941 pw.println(" Processes that are on old until the system is ready:");
7942 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007943 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945
Dianne Hackborn287952c2010-09-22 22:34:31 -07007946 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007947
7948 if (mProcessCrashTimes.getMap().size() > 0) {
7949 if (needSep) pw.println(" ");
7950 needSep = true;
7951 pw.println(" Time since processes crashed:");
7952 long now = SystemClock.uptimeMillis();
7953 for (Map.Entry<String, SparseArray<Long>> procs
7954 : mProcessCrashTimes.getMap().entrySet()) {
7955 SparseArray<Long> uids = procs.getValue();
7956 final int N = uids.size();
7957 for (int i=0; i<N; i++) {
7958 pw.print(" Process "); pw.print(procs.getKey());
7959 pw.print(" uid "); pw.print(uids.keyAt(i));
7960 pw.print(": last crashed ");
7961 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007962 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007963 }
7964 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007965 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007966
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007967 if (mBadProcesses.getMap().size() > 0) {
7968 if (needSep) pw.println(" ");
7969 needSep = true;
7970 pw.println(" Bad processes:");
7971 for (Map.Entry<String, SparseArray<Long>> procs
7972 : mBadProcesses.getMap().entrySet()) {
7973 SparseArray<Long> uids = procs.getValue();
7974 final int N = uids.size();
7975 for (int i=0; i<N; i++) {
7976 pw.print(" Bad process "); pw.print(procs.getKey());
7977 pw.print(" uid "); pw.print(uids.keyAt(i));
7978 pw.print(": crashed at time ");
7979 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 }
7981 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007983
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007984 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007985 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007986 if (mHeavyWeightProcess != null) {
7987 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7988 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007989 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007990 if (dumpAll) {
7991 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07007992 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07007993 pw.println(" mScreenCompatPackages:");
7994 for (Map.Entry<String, Integer> entry
7995 : mCompatModePackages.getPackages().entrySet()) {
7996 String pkg = entry.getKey();
7997 int mode = entry.getValue();
7998 pw.print(" "); pw.print(pkg); pw.print(": ");
7999 pw.print(mode); pw.println();
8000 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07008001 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008002 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008003 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
8004 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
8005 || mOrigWaitForDebugger) {
8006 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
8007 + " mDebugTransient=" + mDebugTransient
8008 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
8009 }
8010 if (mAlwaysFinishActivities || mController != null) {
8011 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
8012 + " mController=" + mController);
8013 }
8014 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008015 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008016 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008017 + " mProcessesReady=" + mProcessesReady
8018 + " mSystemReady=" + mSystemReady);
8019 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008020 + " mBooted=" + mBooted
8021 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008022 pw.print(" mLastPowerCheckRealtime=");
8023 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
8024 pw.println("");
8025 pw.print(" mLastPowerCheckUptime=");
8026 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
8027 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008028 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8029 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008030 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008031 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008032
8033 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008034 }
8035
Dianne Hackborn287952c2010-09-22 22:34:31 -07008036 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
8037 int opti, boolean needSep, boolean dumpAll) {
8038 if (mProcessesToGc.size() > 0) {
8039 if (needSep) pw.println(" ");
8040 needSep = true;
8041 pw.println(" Processes that are waiting to GC:");
8042 long now = SystemClock.uptimeMillis();
8043 for (int i=0; i<mProcessesToGc.size(); i++) {
8044 ProcessRecord proc = mProcessesToGc.get(i);
8045 pw.print(" Process "); pw.println(proc);
8046 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8047 pw.print(", last gced=");
8048 pw.print(now-proc.lastRequestedGc);
8049 pw.print(" ms ago, last lowMem=");
8050 pw.print(now-proc.lastLowMemory);
8051 pw.println(" ms ago");
8052
8053 }
8054 }
8055 return needSep;
8056 }
8057
8058 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8059 int opti, boolean dumpAll) {
8060 boolean needSep = false;
8061
8062 if (mLruProcesses.size() > 0) {
8063 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
8064
8065 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
8066 @Override
8067 public int compare(ProcessRecord object1, ProcessRecord object2) {
8068 if (object1.setAdj != object2.setAdj) {
8069 return object1.setAdj > object2.setAdj ? -1 : 1;
8070 }
8071 if (object1.setSchedGroup != object2.setSchedGroup) {
8072 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
8073 }
8074 if (object1.keeping != object2.keeping) {
8075 return object1.keeping ? -1 : 1;
8076 }
8077 if (object1.pid != object2.pid) {
8078 return object1.pid > object2.pid ? -1 : 1;
8079 }
8080 return 0;
8081 }
8082 };
8083
8084 Collections.sort(procs, comparator);
8085
8086 if (needSep) pw.println(" ");
8087 needSep = true;
8088 pw.println(" Process OOM control:");
8089 dumpProcessOomList(pw, this, procs, " ",
8090 "Proc", "PERS", true);
8091 needSep = true;
8092 }
8093
8094 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
8095
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008096 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008097 pw.println(" mHomeProcess: " + mHomeProcess);
8098 if (mHeavyWeightProcess != null) {
8099 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8100 }
8101
8102 return true;
8103 }
8104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008105 /**
8106 * There are three ways to call this:
8107 * - no service specified: dump all the services
8108 * - a flattened component name that matched an existing service was specified as the
8109 * first arg: dump that one service
8110 * - the first arg isn't the flattened component name of an existing service:
8111 * dump all services whose component contains the first arg as a substring
8112 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008113 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8114 int opti, boolean dumpAll) {
8115 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008116
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008117 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008118 synchronized (this) {
8119 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008120 services.add(r1);
8121 }
8122 }
8123 } else {
8124 ComponentName componentName = name != null
8125 ? ComponentName.unflattenFromString(name) : null;
8126 int objectId = 0;
8127 if (componentName == null) {
8128 // Not a '/' separated full component name; maybe an object ID?
8129 try {
8130 objectId = Integer.parseInt(name, 16);
8131 name = null;
8132 componentName = null;
8133 } catch (RuntimeException e) {
8134 }
8135 }
8136
8137 synchronized (this) {
8138 for (ServiceRecord r1 : mServices.values()) {
8139 if (componentName != null) {
8140 if (r1.name.equals(componentName)) {
8141 services.add(r1);
8142 }
8143 } else if (name != null) {
8144 if (r1.name.flattenToString().contains(name)) {
8145 services.add(r1);
8146 }
8147 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008148 services.add(r1);
8149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008150 }
8151 }
8152 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008153
8154 if (services.size() <= 0) {
8155 return false;
8156 }
8157
8158 boolean needSep = false;
8159 for (int i=0; i<services.size(); i++) {
8160 if (needSep) {
8161 pw.println();
8162 }
8163 needSep = true;
8164 dumpService("", fd, pw, services.get(i), args, dumpAll);
8165 }
8166 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008167 }
8168
8169 /**
8170 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8171 * there is a thread associated with the service.
8172 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008173 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8174 final ServiceRecord r, String[] args, boolean dumpAll) {
8175 String innerPrefix = prefix + " ";
8176 synchronized (this) {
8177 pw.print(prefix); pw.print("SERVICE ");
8178 pw.print(r.shortName); pw.print(" ");
8179 pw.print(Integer.toHexString(System.identityHashCode(r)));
8180 pw.print(" pid=");
8181 if (r.app != null) pw.println(r.app.pid);
8182 else pw.println("(not running)");
8183 if (dumpAll) {
8184 r.dump(pw, innerPrefix);
8185 }
8186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008187 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008188 pw.print(prefix); pw.println(" Client:");
8189 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008190 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008191 TransferPipe tp = new TransferPipe();
8192 try {
8193 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8194 tp.setBufferPrefix(prefix + " ");
8195 tp.go(fd);
8196 } finally {
8197 tp.kill();
8198 }
8199 } catch (IOException e) {
8200 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008201 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008202 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008203 }
8204 }
8205 }
8206
Dianne Hackborn625ac272010-09-17 18:29:22 -07008207 /**
8208 * There are three things that cmd can be:
8209 * - a flattened component name that matched an existing activity
8210 * - the cmd arg isn't the flattened component name of an existing activity:
8211 * dump all activity whose component contains the cmd as a substring
8212 * - A hex number of the ActivityRecord object instance.
8213 */
8214 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8215 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008216 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008217
8218 if ("all".equals(name)) {
8219 synchronized (this) {
8220 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008221 activities.add(r1);
8222 }
8223 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008224 } else {
8225 ComponentName componentName = ComponentName.unflattenFromString(name);
8226 int objectId = 0;
8227 if (componentName == null) {
8228 // Not a '/' separated full component name; maybe an object ID?
8229 try {
8230 objectId = Integer.parseInt(name, 16);
8231 name = null;
8232 componentName = null;
8233 } catch (RuntimeException e) {
8234 }
8235 }
8236
8237 synchronized (this) {
8238 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
8239 if (componentName != null) {
8240 if (r1.intent.getComponent().equals(componentName)) {
8241 activities.add(r1);
8242 }
8243 } else if (name != null) {
8244 if (r1.intent.getComponent().flattenToString().contains(name)) {
8245 activities.add(r1);
8246 }
8247 } else if (System.identityHashCode(r1) == objectId) {
8248 activities.add(r1);
8249 }
8250 }
8251 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008252 }
8253
8254 if (activities.size() <= 0) {
8255 return false;
8256 }
8257
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008258 String[] newArgs = new String[args.length - opti];
8259 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8260
Dianne Hackborn30d71892010-12-11 10:37:55 -08008261 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008262 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008263 for (int i=activities.size()-1; i>=0; i--) {
8264 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008265 if (needSep) {
8266 pw.println();
8267 }
8268 needSep = true;
8269 synchronized (this) {
8270 if (lastTask != r.task) {
8271 lastTask = r.task;
8272 pw.print("TASK "); pw.print(lastTask.affinity);
8273 pw.print(" id="); pw.println(lastTask.taskId);
8274 if (dumpAll) {
8275 lastTask.dump(pw, " ");
8276 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008277 }
8278 }
8279 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008280 }
8281 return true;
8282 }
8283
8284 /**
8285 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8286 * there is a thread associated with the activity.
8287 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008288 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008289 final ActivityRecord r, String[] args, boolean dumpAll) {
8290 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008291 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008292 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8293 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8294 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008295 if (r.app != null) pw.println(r.app.pid);
8296 else pw.println("(not running)");
8297 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008298 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008299 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008300 }
8301 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008302 // flush anything that is already in the PrintWriter since the thread is going
8303 // to write to the file descriptor directly
8304 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008305 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008306 TransferPipe tp = new TransferPipe();
8307 try {
8308 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8309 innerPrefix, args);
8310 tp.go(fd);
8311 } finally {
8312 tp.kill();
8313 }
8314 } catch (IOException e) {
8315 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008316 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008317 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008318 }
8319 }
8320 }
8321
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008322 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8323 int opti, boolean dumpAll) {
8324 boolean needSep = false;
8325
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008326 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008327 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008329 pw.println(" Registered Receivers:");
8330 Iterator it = mRegisteredReceivers.values().iterator();
8331 while (it.hasNext()) {
8332 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008333 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008334 r.dump(pw, " ");
8335 }
8336 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008337
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008338 pw.println();
8339 pw.println(" Receiver Resolver Table:");
8340 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008341 needSep = true;
8342 }
8343
8344 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8345 || mPendingBroadcast != null) {
8346 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008347 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008348 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008349 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008350 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8351 pw.println(" Broadcast #" + i + ":");
8352 mParallelBroadcasts.get(i).dump(pw, " ");
8353 }
8354 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008355 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008356 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008357 }
8358 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8359 pw.println(" Serialized Broadcast #" + i + ":");
8360 mOrderedBroadcasts.get(i).dump(pw, " ");
8361 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008362 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008363 pw.println(" Pending broadcast:");
8364 if (mPendingBroadcast != null) {
8365 mPendingBroadcast.dump(pw, " ");
8366 } else {
8367 pw.println(" (null)");
8368 }
8369 needSep = true;
8370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008371
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008372 if (needSep) {
8373 pw.println();
8374 }
8375 pw.println(" Historical broadcasts:");
8376 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8377 BroadcastRecord r = mBroadcastHistory[i];
8378 if (r == null) {
8379 break;
8380 }
8381 if (dumpAll) {
8382 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8383 r.dump(pw, " ");
8384 } else {
8385 if (i >= 50) {
8386 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008387 break;
8388 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008389 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008390 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008391 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008392 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008393
8394 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008395 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008396 pw.println(" Sticky broadcasts:");
8397 StringBuilder sb = new StringBuilder(128);
8398 for (Map.Entry<String, ArrayList<Intent>> ent
8399 : mStickyBroadcasts.entrySet()) {
8400 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008401 if (dumpAll) {
8402 pw.println(":");
8403 ArrayList<Intent> intents = ent.getValue();
8404 final int N = intents.size();
8405 for (int i=0; i<N; i++) {
8406 sb.setLength(0);
8407 sb.append(" Intent: ");
8408 intents.get(i).toShortString(sb, true, false);
8409 pw.println(sb.toString());
8410 Bundle bundle = intents.get(i).getExtras();
8411 if (bundle != null) {
8412 pw.print(" ");
8413 pw.println(bundle.toString());
8414 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008415 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008416 } else {
8417 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008418 }
8419 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008420 needSep = true;
8421 }
8422
8423 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008424 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008425 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008426 pw.println(" mHandler:");
8427 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008428 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008429 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008430
8431 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008432 }
8433
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008434 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008435 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008436 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008437
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008438 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8439 if (mServices.size() > 0) {
8440 pw.println(" Active services:");
8441 long nowReal = SystemClock.elapsedRealtime();
8442 Iterator<ServiceRecord> it = mServices.values().iterator();
8443 needSep = false;
8444 while (it.hasNext()) {
8445 ServiceRecord r = it.next();
8446 if (needSep) {
8447 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008448 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008449 pw.print(" * "); pw.println(r);
8450 if (dumpAll) {
8451 r.dump(pw, " ");
8452 needSep = true;
8453 } else {
8454 pw.print(" app="); pw.println(r.app);
8455 pw.print(" created=");
8456 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8457 pw.print(" started="); pw.print(r.startRequested);
8458 pw.print(" connections="); pw.println(r.connections.size());
8459 }
8460 if (dumpClient && r.app != null && r.app.thread != null) {
8461 pw.println(" Client:");
8462 pw.flush();
8463 try {
8464 TransferPipe tp = new TransferPipe();
8465 try {
8466 r.app.thread.dumpService(
8467 tp.getWriteFd().getFileDescriptor(), r, args);
8468 tp.setBufferPrefix(" ");
8469 // Short timeout, since blocking here can
8470 // deadlock with the application.
8471 tp.go(fd, 2000);
8472 } finally {
8473 tp.kill();
8474 }
8475 } catch (IOException e) {
8476 pw.println(" Failure while dumping the service: " + e);
8477 } catch (RemoteException e) {
8478 pw.println(" Got a RemoteException while dumping the service");
8479 }
8480 needSep = true;
8481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008482 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008483 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008485
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008486 if (mPendingServices.size() > 0) {
8487 if (needSep) pw.println(" ");
8488 pw.println(" Pending services:");
8489 for (int i=0; i<mPendingServices.size(); i++) {
8490 ServiceRecord r = mPendingServices.get(i);
8491 pw.print(" * Pending "); pw.println(r);
8492 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008493 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008494 needSep = true;
8495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008496
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008497 if (mRestartingServices.size() > 0) {
8498 if (needSep) pw.println(" ");
8499 pw.println(" Restarting services:");
8500 for (int i=0; i<mRestartingServices.size(); i++) {
8501 ServiceRecord r = mRestartingServices.get(i);
8502 pw.print(" * Restarting "); pw.println(r);
8503 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008504 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008505 needSep = true;
8506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008507
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008508 if (mStoppingServices.size() > 0) {
8509 if (needSep) pw.println(" ");
8510 pw.println(" Stopping services:");
8511 for (int i=0; i<mStoppingServices.size(); i++) {
8512 ServiceRecord r = mStoppingServices.get(i);
8513 pw.print(" * Stopping "); pw.println(r);
8514 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008516 needSep = true;
8517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008519 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 if (mServiceConnections.size() > 0) {
8521 if (needSep) pw.println(" ");
8522 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008523 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008524 = mServiceConnections.values().iterator();
8525 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008526 ArrayList<ConnectionRecord> r = it.next();
8527 for (int i=0; i<r.size(); i++) {
8528 pw.print(" * "); pw.println(r.get(i));
8529 r.get(i).dump(pw, " ");
8530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008531 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008532 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008533 }
8534 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008535
8536 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 }
8538
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008539 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8540 int opti, boolean dumpAll) {
8541 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008542
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008543 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8544 if (mProvidersByClass.size() > 0) {
8545 if (needSep) pw.println(" ");
8546 pw.println(" Published content providers (by class):");
8547 Iterator<Map.Entry<String, ContentProviderRecord>> it
8548 = mProvidersByClass.entrySet().iterator();
8549 while (it.hasNext()) {
8550 Map.Entry<String, ContentProviderRecord> e = it.next();
8551 ContentProviderRecord r = e.getValue();
8552 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008553 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008554 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008555 } else {
8556 pw.print(" * "); pw.print(r.name.toShortString());
8557 if (r.app != null) {
8558 pw.println(":");
8559 pw.print(" "); pw.println(r.app);
8560 } else {
8561 pw.println();
8562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008564 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008565 needSep = true;
8566 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008567
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008568 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008569 if (mProvidersByName.size() > 0) {
8570 pw.println(" ");
8571 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008572 Iterator<Map.Entry<String, ContentProviderRecord>> it
8573 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008574 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008575 Map.Entry<String, ContentProviderRecord> e = it.next();
8576 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008577 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8578 pw.println(r);
8579 }
8580 needSep = true;
8581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008582 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008583
8584 if (mLaunchingProviders.size() > 0) {
8585 if (needSep) pw.println(" ");
8586 pw.println(" Launching content providers:");
8587 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8588 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8589 pw.println(mLaunchingProviders.get(i));
8590 }
8591 needSep = true;
8592 }
8593
8594 if (mGrantedUriPermissions.size() > 0) {
8595 pw.println();
8596 pw.println("Granted Uri Permissions:");
8597 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8598 int uid = mGrantedUriPermissions.keyAt(i);
8599 HashMap<Uri, UriPermission> perms
8600 = mGrantedUriPermissions.valueAt(i);
8601 pw.print(" * UID "); pw.print(uid);
8602 pw.println(" holds:");
8603 for (UriPermission perm : perms.values()) {
8604 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008605 if (dumpAll) {
8606 perm.dump(pw, " ");
8607 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008608 }
8609 }
8610 needSep = true;
8611 }
8612
8613 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 }
8615
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008616 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8617 int opti, boolean dumpAll) {
8618 boolean needSep = false;
8619
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008620 if (this.mIntentSenderRecords.size() > 0) {
8621 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8622 Iterator<WeakReference<PendingIntentRecord>> it
8623 = mIntentSenderRecords.values().iterator();
8624 while (it.hasNext()) {
8625 WeakReference<PendingIntentRecord> ref = it.next();
8626 PendingIntentRecord rec = ref != null ? ref.get(): null;
8627 needSep = true;
8628 if (rec != null) {
8629 pw.print(" * "); pw.println(rec);
8630 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008631 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008632 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008633 } else {
8634 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008635 }
8636 }
8637 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008638
8639 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008640 }
8641
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008642 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8643 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008645 boolean needNL = false;
8646 final String innerPrefix = prefix + " ";
8647 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008648 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008649 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008650 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008651 if (needNL) {
8652 pw.println(" ");
8653 needNL = false;
8654 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008655 if (lastTask != r.task) {
8656 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008657 pw.print(prefix);
8658 pw.print(full ? "* " : " ");
8659 pw.println(lastTask);
8660 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008661 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008662 } else if (complete) {
8663 // Complete + brief == give a summary. Isn't that obvious?!?
8664 if (lastTask.intent != null) {
8665 pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
8666 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008668 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008669 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8670 pw.print(" #"); pw.print(i); pw.print(": ");
8671 pw.println(r);
8672 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008673 r.dump(pw, innerPrefix);
8674 } else if (complete) {
8675 // Complete + brief == give a summary. Isn't that obvious?!?
8676 pw.print(innerPrefix); pw.println(r.intent);
8677 if (r.app != null) {
8678 pw.print(innerPrefix); pw.println(r.app);
8679 }
8680 }
8681 if (client && r.app != null && r.app.thread != null) {
8682 // flush anything that is already in the PrintWriter since the thread is going
8683 // to write to the file descriptor directly
8684 pw.flush();
8685 try {
8686 TransferPipe tp = new TransferPipe();
8687 try {
8688 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8689 innerPrefix, args);
8690 // Short timeout, since blocking here can
8691 // deadlock with the application.
8692 tp.go(fd, 2000);
8693 } finally {
8694 tp.kill();
8695 }
8696 } catch (IOException e) {
8697 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8698 } catch (RemoteException e) {
8699 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8700 }
8701 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008703 }
8704 }
8705
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008706 private static String buildOomTag(String prefix, String space, int val, int base) {
8707 if (val == base) {
8708 if (space == null) return prefix;
8709 return prefix + " ";
8710 }
8711 return prefix + "+" + Integer.toString(val-base);
8712 }
8713
8714 private static final int dumpProcessList(PrintWriter pw,
8715 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008716 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008717 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008718 final int N = list.size()-1;
8719 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008720 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008721 pw.println(String.format("%s%s #%2d: %s",
8722 prefix, (r.persistent ? persistentLabel : normalLabel),
8723 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008724 if (r.persistent) {
8725 numPers++;
8726 }
8727 }
8728 return numPers;
8729 }
8730
Dianne Hackborn287952c2010-09-22 22:34:31 -07008731 private static final void dumpProcessOomList(PrintWriter pw,
8732 ActivityManagerService service, List<ProcessRecord> list,
8733 String prefix, String normalLabel, String persistentLabel,
8734 boolean inclDetails) {
8735
8736 final long curRealtime = SystemClock.elapsedRealtime();
8737 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8738 final long curUptime = SystemClock.uptimeMillis();
8739 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8740
8741 final int N = list.size()-1;
8742 for (int i=N; i>=0; i--) {
8743 ProcessRecord r = list.get(i);
8744 String oomAdj;
8745 if (r.setAdj >= EMPTY_APP_ADJ) {
8746 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8747 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8748 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8749 } else if (r.setAdj >= HOME_APP_ADJ) {
8750 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8751 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8752 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8753 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8754 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8755 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8756 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8757 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8758 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8759 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8760 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8761 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8762 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8763 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8764 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8765 } else if (r.setAdj >= SYSTEM_ADJ) {
8766 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8767 } else {
8768 oomAdj = Integer.toString(r.setAdj);
8769 }
8770 String schedGroup;
8771 switch (r.setSchedGroup) {
8772 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8773 schedGroup = "B";
8774 break;
8775 case Process.THREAD_GROUP_DEFAULT:
8776 schedGroup = "F";
8777 break;
8778 default:
8779 schedGroup = Integer.toString(r.setSchedGroup);
8780 break;
8781 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008782 String foreground;
8783 if (r.foregroundActivities) {
8784 foreground = "A";
8785 } else if (r.foregroundServices) {
8786 foreground = "S";
8787 } else {
8788 foreground = " ";
8789 }
8790 pw.println(String.format("%s%s #%2d: adj=%s/%s%s %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008791 prefix, (r.persistent ? persistentLabel : normalLabel),
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008792 N-i, oomAdj, schedGroup, foreground, r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07008793 if (r.adjSource != null || r.adjTarget != null) {
8794 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008795 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008796 if (r.adjTarget instanceof ComponentName) {
8797 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8798 } else if (r.adjTarget != null) {
8799 pw.print(r.adjTarget.toString());
8800 } else {
8801 pw.print("{null}");
8802 }
8803 pw.print("<=");
8804 if (r.adjSource instanceof ProcessRecord) {
8805 pw.print("Proc{");
8806 pw.print(((ProcessRecord)r.adjSource).toShortString());
8807 pw.println("}");
8808 } else if (r.adjSource != null) {
8809 pw.println(r.adjSource.toString());
8810 } else {
8811 pw.println("{null}");
8812 }
8813 }
8814 if (inclDetails) {
8815 pw.print(prefix);
8816 pw.print(" ");
8817 pw.print("oom: max="); pw.print(r.maxAdj);
8818 pw.print(" hidden="); pw.print(r.hiddenAdj);
8819 pw.print(" curRaw="); pw.print(r.curRawAdj);
8820 pw.print(" setRaw="); pw.print(r.setRawAdj);
8821 pw.print(" cur="); pw.print(r.curAdj);
8822 pw.print(" set="); pw.println(r.setAdj);
8823 pw.print(prefix);
8824 pw.print(" ");
8825 pw.print("keeping="); pw.print(r.keeping);
8826 pw.print(" hidden="); pw.print(r.hidden);
8827 pw.print(" empty="); pw.println(r.empty);
8828
8829 if (!r.keeping) {
8830 if (r.lastWakeTime != 0) {
8831 long wtime;
8832 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8833 synchronized (stats) {
8834 wtime = stats.getProcessWakeTime(r.info.uid,
8835 r.pid, curRealtime);
8836 }
8837 long timeUsed = wtime - r.lastWakeTime;
8838 pw.print(prefix);
8839 pw.print(" ");
8840 pw.print("keep awake over ");
8841 TimeUtils.formatDuration(realtimeSince, pw);
8842 pw.print(" used ");
8843 TimeUtils.formatDuration(timeUsed, pw);
8844 pw.print(" (");
8845 pw.print((timeUsed*100)/realtimeSince);
8846 pw.println("%)");
8847 }
8848 if (r.lastCpuTime != 0) {
8849 long timeUsed = r.curCpuTime - r.lastCpuTime;
8850 pw.print(prefix);
8851 pw.print(" ");
8852 pw.print("run cpu over ");
8853 TimeUtils.formatDuration(uptimeSince, pw);
8854 pw.print(" used ");
8855 TimeUtils.formatDuration(timeUsed, pw);
8856 pw.print(" (");
8857 pw.print((timeUsed*100)/uptimeSince);
8858 pw.println("%)");
8859 }
8860 }
8861 }
8862 }
8863 }
8864
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008865 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
8866 ArrayList<ProcessRecord> procs;
8867 synchronized (this) {
8868 if (args != null && args.length > 0
8869 && args[0].charAt(0) != '-') {
8870 procs = new ArrayList<ProcessRecord>();
8871 int pid = -1;
8872 try {
8873 pid = Integer.parseInt(args[0]);
8874 } catch (NumberFormatException e) {
8875
8876 }
8877 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8878 ProcessRecord proc = mLruProcesses.get(i);
8879 if (proc.pid == pid) {
8880 procs.add(proc);
8881 } else if (proc.processName.equals(args[0])) {
8882 procs.add(proc);
8883 }
8884 }
8885 if (procs.size() <= 0) {
8886 pw.println("No process found for: " + args[0]);
8887 return null;
8888 }
8889 } else {
8890 procs = new ArrayList<ProcessRecord>(mLruProcesses);
8891 }
8892 }
8893 return procs;
8894 }
8895
8896 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
8897 PrintWriter pw, String[] args) {
8898 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8899 if (procs == null) {
8900 return;
8901 }
8902
8903 long uptime = SystemClock.uptimeMillis();
8904 long realtime = SystemClock.elapsedRealtime();
8905 pw.println("Applications Graphics Acceleration Info:");
8906 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8907
8908 String callArgs[] = {"graphics"};
8909 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8910 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008911 if (r.thread != null) {
8912 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
8913 pw.flush();
8914 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008915 TransferPipe.goDump(r.thread.asBinder(), fd, callArgs);
8916 } catch (IOException e) {
8917 pw.println("Failure: " + e);
8918 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07008919 } catch (RemoteException e) {
8920 pw.println("Got RemoteException!");
8921 pw.flush();
8922 }
8923 }
8924 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07008925 }
8926
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008927 final void dumpApplicationMemoryUsage(FileDescriptor fd,
8928 PrintWriter pw, String prefix, String[] args) {
8929 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8930 if (procs == null) {
8931 return;
8932 }
8933
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008934 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008935 long uptime = SystemClock.uptimeMillis();
8936 long realtime = SystemClock.elapsedRealtime();
8937
8938 if (isCheckinRequest) {
8939 // short checkin version
8940 pw.println(uptime + "," + realtime);
8941 pw.flush();
8942 } else {
8943 pw.println("Applications Memory Usage (kB):");
8944 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8945 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008946 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8947 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008948 if (r.thread != null) {
8949 if (!isCheckinRequest) {
8950 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8951 pw.flush();
8952 }
8953 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008954 TransferPipe.goDump(r.thread.asBinder(), fd, args);
8955 } catch (IOException e) {
8956 pw.println("Failure: " + e);
8957 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008958 } catch (RemoteException e) {
8959 if (!isCheckinRequest) {
8960 pw.println("Got RemoteException!");
8961 pw.flush();
8962 }
8963 }
8964 }
8965 }
8966 }
8967
8968 /**
8969 * Searches array of arguments for the specified string
8970 * @param args array of argument strings
8971 * @param value value to search for
8972 * @return true if the value is contained in the array
8973 */
8974 private static boolean scanArgs(String[] args, String value) {
8975 if (args != null) {
8976 for (String arg : args) {
8977 if (value.equals(arg)) {
8978 return true;
8979 }
8980 }
8981 }
8982 return false;
8983 }
8984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008985 private final void killServicesLocked(ProcessRecord app,
8986 boolean allowRestart) {
8987 // Report disconnected services.
8988 if (false) {
8989 // XXX we are letting the client link to the service for
8990 // death notifications.
8991 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008992 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008993 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008994 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008995 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008996 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008997 = r.connections.values().iterator();
8998 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008999 ArrayList<ConnectionRecord> cl = jt.next();
9000 for (int i=0; i<cl.size(); i++) {
9001 ConnectionRecord c = cl.get(i);
9002 if (c.binding.client != app) {
9003 try {
9004 //c.conn.connected(r.className, null);
9005 } catch (Exception e) {
9006 // todo: this should be asynchronous!
9007 Slog.w(TAG, "Exception thrown disconnected servce "
9008 + r.shortName
9009 + " from app " + app.processName, e);
9010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009011 }
9012 }
9013 }
9014 }
9015 }
9016 }
9017 }
9018
9019 // Clean up any connections this application has to other services.
9020 if (app.connections.size() > 0) {
9021 Iterator<ConnectionRecord> it = app.connections.iterator();
9022 while (it.hasNext()) {
9023 ConnectionRecord r = it.next();
9024 removeConnectionLocked(r, app, null);
9025 }
9026 }
9027 app.connections.clear();
9028
9029 if (app.services.size() != 0) {
9030 // Any services running in the application need to be placed
9031 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009032 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009033 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009034 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009035 synchronized (sr.stats.getBatteryStats()) {
9036 sr.stats.stopLaunchedLocked();
9037 }
9038 sr.app = null;
9039 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009040 if (mStoppingServices.remove(sr)) {
9041 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
9042 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009043
9044 boolean hasClients = sr.bindings.size() > 0;
9045 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009046 Iterator<IntentBindRecord> bindings
9047 = sr.bindings.values().iterator();
9048 while (bindings.hasNext()) {
9049 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009050 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009051 + ": shouldUnbind=" + b.hasBound);
9052 b.binder = null;
9053 b.requested = b.received = b.hasBound = false;
9054 }
9055 }
9056
Dianne Hackborn070783f2010-12-29 16:46:28 -08009057 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
9058 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009059 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009060 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009061 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009062 sr.crashCount, sr.shortName, app.pid);
9063 bringDownServiceLocked(sr, true);
9064 } else if (!allowRestart) {
9065 bringDownServiceLocked(sr, true);
9066 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009067 boolean canceled = scheduleServiceRestartLocked(sr, true);
9068
9069 // Should the service remain running? Note that in the
9070 // extreme case of so many attempts to deliver a command
9071 // that it failed, that we also will stop it here.
9072 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
9073 if (sr.pendingStarts.size() == 0) {
9074 sr.startRequested = false;
9075 if (!hasClients) {
9076 // Whoops, no reason to restart!
9077 bringDownServiceLocked(sr, true);
9078 }
9079 }
9080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 }
9082 }
9083
9084 if (!allowRestart) {
9085 app.services.clear();
9086 }
9087 }
9088
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009089 // Make sure we have no more records on the stopping list.
9090 int i = mStoppingServices.size();
9091 while (i > 0) {
9092 i--;
9093 ServiceRecord sr = mStoppingServices.get(i);
9094 if (sr.app == app) {
9095 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009096 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009097 }
9098 }
9099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009100 app.executingServices.clear();
9101 }
9102
9103 private final void removeDyingProviderLocked(ProcessRecord proc,
9104 ContentProviderRecord cpr) {
9105 synchronized (cpr) {
9106 cpr.launchingApp = null;
9107 cpr.notifyAll();
9108 }
9109
9110 mProvidersByClass.remove(cpr.info.name);
9111 String names[] = cpr.info.authority.split(";");
9112 for (int j = 0; j < names.length; j++) {
9113 mProvidersByName.remove(names[j]);
9114 }
9115
9116 Iterator<ProcessRecord> cit = cpr.clients.iterator();
9117 while (cit.hasNext()) {
9118 ProcessRecord capp = cit.next();
9119 if (!capp.persistent && capp.thread != null
9120 && capp.pid != 0
9121 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009122 Slog.i(TAG, "Kill " + capp.processName
9123 + " (pid " + capp.pid + "): provider " + cpr.info.name
9124 + " in dying process " + proc.processName);
9125 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
9126 capp.processName, capp.setAdj, "dying provider " + proc.processName);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009127 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009128 }
9129 }
9130
9131 mLaunchingProviders.remove(cpr);
9132 }
9133
9134 /**
9135 * Main code for cleaning up a process when it has gone away. This is
9136 * called both as a result of the process dying, or directly when stopping
9137 * a process when running in single process mode.
9138 */
9139 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
9140 boolean restarting, int index) {
9141 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009142 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009143 }
9144
Dianne Hackborn36124872009-10-08 16:22:03 -07009145 mProcessesToGc.remove(app);
9146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009147 // Dismiss any open dialogs.
9148 if (app.crashDialog != null) {
9149 app.crashDialog.dismiss();
9150 app.crashDialog = null;
9151 }
9152 if (app.anrDialog != null) {
9153 app.anrDialog.dismiss();
9154 app.anrDialog = null;
9155 }
9156 if (app.waitDialog != null) {
9157 app.waitDialog.dismiss();
9158 app.waitDialog = null;
9159 }
9160
9161 app.crashing = false;
9162 app.notResponding = false;
9163
9164 app.resetPackageList();
9165 app.thread = null;
9166 app.forcingToForeground = null;
9167 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009168 app.foregroundActivities = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009169
9170 killServicesLocked(app, true);
9171
9172 boolean restart = false;
9173
9174 int NL = mLaunchingProviders.size();
9175
9176 // Remove published content providers.
9177 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009178 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009180 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 cpr.provider = null;
9182 cpr.app = null;
9183
9184 // See if someone is waiting for this provider... in which
9185 // case we don't remove it, but just let it restart.
9186 int i = 0;
9187 if (!app.bad) {
9188 for (; i<NL; i++) {
9189 if (mLaunchingProviders.get(i) == cpr) {
9190 restart = true;
9191 break;
9192 }
9193 }
9194 } else {
9195 i = NL;
9196 }
9197
9198 if (i >= NL) {
9199 removeDyingProviderLocked(app, cpr);
9200 NL = mLaunchingProviders.size();
9201 }
9202 }
9203 app.pubProviders.clear();
9204 }
9205
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009206 // Take care of any launching providers waiting for this process.
9207 if (checkAppInLaunchingProvidersLocked(app, false)) {
9208 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009209 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009211 // Unregister from connected content providers.
9212 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009213 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009214 while (it.hasNext()) {
9215 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9216 cpr.clients.remove(app);
9217 }
9218 app.conProviders.clear();
9219 }
9220
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009221 // At this point there may be remaining entries in mLaunchingProviders
9222 // where we were the only one waiting, so they are no longer of use.
9223 // Look for these and clean up if found.
9224 // XXX Commented out for now. Trying to figure out a way to reproduce
9225 // the actual situation to identify what is actually going on.
9226 if (false) {
9227 for (int i=0; i<NL; i++) {
9228 ContentProviderRecord cpr = (ContentProviderRecord)
9229 mLaunchingProviders.get(i);
9230 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9231 synchronized (cpr) {
9232 cpr.launchingApp = null;
9233 cpr.notifyAll();
9234 }
9235 }
9236 }
9237 }
9238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009239 skipCurrentReceiverLocked(app);
9240
9241 // Unregister any receivers.
9242 if (app.receivers.size() > 0) {
9243 Iterator<ReceiverList> it = app.receivers.iterator();
9244 while (it.hasNext()) {
9245 removeReceiverLocked(it.next());
9246 }
9247 app.receivers.clear();
9248 }
9249
Christopher Tate181fafa2009-05-14 11:12:14 -07009250 // If the app is undergoing backup, tell the backup manager about it
9251 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009252 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009253 try {
9254 IBackupManager bm = IBackupManager.Stub.asInterface(
9255 ServiceManager.getService(Context.BACKUP_SERVICE));
9256 bm.agentDisconnected(app.info.packageName);
9257 } catch (RemoteException e) {
9258 // can't happen; backup manager is local
9259 }
9260 }
9261
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009262 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app).sendToTarget();
9263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009264 // If the caller is restarting this app, then leave it in its
9265 // current lists and let the caller take care of it.
9266 if (restarting) {
9267 return;
9268 }
9269
9270 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009271 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009272 "Removing non-persistent process during cleanup: " + app);
9273 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009274 if (mHeavyWeightProcess == app) {
9275 mHeavyWeightProcess = null;
9276 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009278 } else if (!app.removed) {
9279 // This app is persistent, so we need to keep its record around.
9280 // If it is not already on the pending app list, add it there
9281 // and start a new process for it.
9282 app.thread = null;
9283 app.forcingToForeground = null;
9284 app.foregroundServices = false;
9285 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9286 mPersistentStartingProcesses.add(app);
9287 restart = true;
9288 }
9289 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009290 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9291 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009292 mProcessesOnHold.remove(app);
9293
The Android Open Source Project4df24232009-03-05 14:34:35 -08009294 if (app == mHomeProcess) {
9295 mHomeProcess = null;
9296 }
9297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009298 if (restart) {
9299 // We have components that still need to be running in the
9300 // process, so re-launch it.
9301 mProcessNames.put(app.processName, app.info.uid, app);
9302 startProcessLocked(app, "restart", app.processName);
9303 } else if (app.pid > 0 && app.pid != MY_PID) {
9304 // Goodbye!
9305 synchronized (mPidsSelfLocked) {
9306 mPidsSelfLocked.remove(app.pid);
9307 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9308 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009309 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009310 }
9311 }
9312
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009313 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9314 // Look through the content providers we are waiting to have launched,
9315 // and if any run in this process then either schedule a restart of
9316 // the process or kill the client waiting for it if this process has
9317 // gone bad.
9318 int NL = mLaunchingProviders.size();
9319 boolean restart = false;
9320 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009321 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009322 if (cpr.launchingApp == app) {
9323 if (!alwaysBad && !app.bad) {
9324 restart = true;
9325 } else {
9326 removeDyingProviderLocked(app, cpr);
9327 NL = mLaunchingProviders.size();
9328 }
9329 }
9330 }
9331 return restart;
9332 }
9333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009334 // =========================================================
9335 // SERVICES
9336 // =========================================================
9337
9338 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9339 ActivityManager.RunningServiceInfo info =
9340 new ActivityManager.RunningServiceInfo();
9341 info.service = r.name;
9342 if (r.app != null) {
9343 info.pid = r.app.pid;
9344 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009345 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009346 info.process = r.processName;
9347 info.foreground = r.isForeground;
9348 info.activeSince = r.createTime;
9349 info.started = r.startRequested;
9350 info.clientCount = r.connections.size();
9351 info.crashCount = r.crashCount;
9352 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009353 if (r.isForeground) {
9354 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9355 }
9356 if (r.startRequested) {
9357 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9358 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009359 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009360 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9361 }
9362 if (r.app != null && r.app.persistent) {
9363 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9364 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009365
9366 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9367 for (int i=0; i<connl.size(); i++) {
9368 ConnectionRecord conn = connl.get(i);
9369 if (conn.clientLabel != 0) {
9370 info.clientPackage = conn.binding.client.info.packageName;
9371 info.clientLabel = conn.clientLabel;
9372 return info;
9373 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009374 }
9375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009376 return info;
9377 }
9378
9379 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9380 int flags) {
9381 synchronized (this) {
9382 ArrayList<ActivityManager.RunningServiceInfo> res
9383 = new ArrayList<ActivityManager.RunningServiceInfo>();
9384
9385 if (mServices.size() > 0) {
9386 Iterator<ServiceRecord> it = mServices.values().iterator();
9387 while (it.hasNext() && res.size() < maxNum) {
9388 res.add(makeRunningServiceInfoLocked(it.next()));
9389 }
9390 }
9391
9392 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9393 ServiceRecord r = mRestartingServices.get(i);
9394 ActivityManager.RunningServiceInfo info =
9395 makeRunningServiceInfoLocked(r);
9396 info.restarting = r.nextRestartTime;
9397 res.add(info);
9398 }
9399
9400 return res;
9401 }
9402 }
9403
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009404 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9405 synchronized (this) {
9406 ServiceRecord r = mServices.get(name);
9407 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009408 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9409 for (int i=0; i<conn.size(); i++) {
9410 if (conn.get(i).clientIntent != null) {
9411 return conn.get(i).clientIntent;
9412 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009413 }
9414 }
9415 }
9416 }
9417 return null;
9418 }
9419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009420 private final ServiceRecord findServiceLocked(ComponentName name,
9421 IBinder token) {
9422 ServiceRecord r = mServices.get(name);
9423 return r == token ? r : null;
9424 }
9425
9426 private final class ServiceLookupResult {
9427 final ServiceRecord record;
9428 final String permission;
9429
9430 ServiceLookupResult(ServiceRecord _record, String _permission) {
9431 record = _record;
9432 permission = _permission;
9433 }
9434 };
9435
9436 private ServiceLookupResult findServiceLocked(Intent service,
9437 String resolvedType) {
9438 ServiceRecord r = null;
9439 if (service.getComponent() != null) {
9440 r = mServices.get(service.getComponent());
9441 }
9442 if (r == null) {
9443 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9444 r = mServicesByIntent.get(filter);
9445 }
9446
9447 if (r == null) {
9448 try {
9449 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009450 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009451 service, resolvedType, 0);
9452 ServiceInfo sInfo =
9453 rInfo != null ? rInfo.serviceInfo : null;
9454 if (sInfo == null) {
9455 return null;
9456 }
9457
9458 ComponentName name = new ComponentName(
9459 sInfo.applicationInfo.packageName, sInfo.name);
9460 r = mServices.get(name);
9461 } catch (RemoteException ex) {
9462 // pm is in same process, this will never happen.
9463 }
9464 }
9465 if (r != null) {
9466 int callingPid = Binder.getCallingPid();
9467 int callingUid = Binder.getCallingUid();
9468 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009469 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009470 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009471 if (!r.exported) {
9472 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9473 + " from pid=" + callingPid
9474 + ", uid=" + callingUid
9475 + " that is not exported from uid " + r.appInfo.uid);
9476 return new ServiceLookupResult(null, "not exported from uid "
9477 + r.appInfo.uid);
9478 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009479 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009480 + " from pid=" + callingPid
9481 + ", uid=" + callingUid
9482 + " requires " + r.permission);
9483 return new ServiceLookupResult(null, r.permission);
9484 }
9485 return new ServiceLookupResult(r, null);
9486 }
9487 return null;
9488 }
9489
9490 private class ServiceRestarter implements Runnable {
9491 private ServiceRecord mService;
9492
9493 void setService(ServiceRecord service) {
9494 mService = service;
9495 }
9496
9497 public void run() {
9498 synchronized(ActivityManagerService.this) {
9499 performServiceRestartLocked(mService);
9500 }
9501 }
9502 }
9503
9504 private ServiceLookupResult retrieveServiceLocked(Intent service,
9505 String resolvedType, int callingPid, int callingUid) {
9506 ServiceRecord r = null;
9507 if (service.getComponent() != null) {
9508 r = mServices.get(service.getComponent());
9509 }
9510 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9511 r = mServicesByIntent.get(filter);
9512 if (r == null) {
9513 try {
9514 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009515 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009516 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009517 ServiceInfo sInfo =
9518 rInfo != null ? rInfo.serviceInfo : null;
9519 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009520 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009521 ": not found");
9522 return null;
9523 }
9524
9525 ComponentName name = new ComponentName(
9526 sInfo.applicationInfo.packageName, sInfo.name);
9527 r = mServices.get(name);
9528 if (r == null) {
9529 filter = new Intent.FilterComparison(service.cloneFilter());
9530 ServiceRestarter res = new ServiceRestarter();
9531 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9532 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9533 synchronized (stats) {
9534 ss = stats.getServiceStatsLocked(
9535 sInfo.applicationInfo.uid, sInfo.packageName,
9536 sInfo.name);
9537 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009538 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009539 res.setService(r);
9540 mServices.put(name, r);
9541 mServicesByIntent.put(filter, r);
9542
9543 // Make sure this component isn't in the pending list.
9544 int N = mPendingServices.size();
9545 for (int i=0; i<N; i++) {
9546 ServiceRecord pr = mPendingServices.get(i);
9547 if (pr.name.equals(name)) {
9548 mPendingServices.remove(i);
9549 i--;
9550 N--;
9551 }
9552 }
9553 }
9554 } catch (RemoteException ex) {
9555 // pm is in same process, this will never happen.
9556 }
9557 }
9558 if (r != null) {
9559 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009560 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009561 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009562 if (!r.exported) {
9563 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9564 + " from pid=" + callingPid
9565 + ", uid=" + callingUid
9566 + " that is not exported from uid " + r.appInfo.uid);
9567 return new ServiceLookupResult(null, "not exported from uid "
9568 + r.appInfo.uid);
9569 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009570 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009571 + " from pid=" + callingPid
9572 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009573 + " requires " + r.permission);
9574 return new ServiceLookupResult(null, r.permission);
9575 }
9576 return new ServiceLookupResult(r, null);
9577 }
9578 return null;
9579 }
9580
Dianne Hackborn287952c2010-09-22 22:34:31 -07009581 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9582 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9583 + why + " of " + r + " in app " + r.app);
9584 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9585 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009586 long now = SystemClock.uptimeMillis();
9587 if (r.executeNesting == 0 && r.app != null) {
9588 if (r.app.executingServices.size() == 0) {
9589 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9590 msg.obj = r.app;
9591 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9592 }
9593 r.app.executingServices.add(r);
9594 }
9595 r.executeNesting++;
9596 r.executingStart = now;
9597 }
9598
9599 private final void sendServiceArgsLocked(ServiceRecord r,
9600 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009601 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009602 if (N == 0) {
9603 return;
9604 }
9605
Dianne Hackborn39792d22010-08-19 18:01:52 -07009606 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009607 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009608 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009609 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9610 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009611 if (si.intent == null && N > 1) {
9612 // If somehow we got a dummy null intent in the middle,
9613 // then skip it. DO NOT skip a null intent when it is
9614 // the only one in the list -- this is to support the
9615 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009616 continue;
9617 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009618 si.deliveredTime = SystemClock.uptimeMillis();
9619 r.deliveredStarts.add(si);
9620 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009621 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009622 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009623 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009624 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009625 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626 if (!oomAdjusted) {
9627 oomAdjusted = true;
9628 updateOomAdjLocked(r.app);
9629 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009630 int flags = 0;
9631 if (si.deliveryCount > 0) {
9632 flags |= Service.START_FLAG_RETRY;
9633 }
9634 if (si.doneExecutingCount > 0) {
9635 flags |= Service.START_FLAG_REDELIVERY;
9636 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009637 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009638 } catch (RemoteException e) {
9639 // Remote process gone... we'll let the normal cleanup take
9640 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009641 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009642 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009644 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009645 break;
9646 }
9647 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009648 }
9649
9650 private final boolean requestServiceBindingLocked(ServiceRecord r,
9651 IntentBindRecord i, boolean rebind) {
9652 if (r.app == null || r.app.thread == null) {
9653 // If service is not currently running, can't yet bind.
9654 return false;
9655 }
9656 if ((!i.requested || rebind) && i.apps.size() > 0) {
9657 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009658 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009659 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9660 if (!rebind) {
9661 i.requested = true;
9662 }
9663 i.hasBound = true;
9664 i.doRebind = false;
9665 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009666 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667 return false;
9668 }
9669 }
9670 return true;
9671 }
9672
9673 private final void requestServiceBindingsLocked(ServiceRecord r) {
9674 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9675 while (bindings.hasNext()) {
9676 IntentBindRecord i = bindings.next();
9677 if (!requestServiceBindingLocked(r, i, false)) {
9678 break;
9679 }
9680 }
9681 }
9682
9683 private final void realStartServiceLocked(ServiceRecord r,
9684 ProcessRecord app) throws RemoteException {
9685 if (app.thread == null) {
9686 throw new RemoteException();
9687 }
9688
9689 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009690 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009691
9692 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009693 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009694 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009695
9696 boolean created = false;
9697 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009698 mStringBuilder.setLength(0);
9699 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009700 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009701 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009702 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009703 synchronized (r.stats.getBatteryStats()) {
9704 r.stats.startLaunchedLocked();
9705 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009706 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04009707 app.thread.scheduleCreateService(r, r.serviceInfo,
9708 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009709 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009710 created = true;
9711 } finally {
9712 if (!created) {
9713 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009714 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009715 }
9716 }
9717
9718 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009719
9720 // If the service is in the started state, and there are no
9721 // pending arguments, then fake up one so its onStartCommand() will
9722 // be called.
9723 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009724 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
9725 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009726 }
9727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009728 sendServiceArgsLocked(r, true);
9729 }
9730
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009731 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9732 boolean allowCancel) {
9733 boolean canceled = false;
9734
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009735 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009736 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009737 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009738
Dianne Hackborn070783f2010-12-29 16:46:28 -08009739 if ((r.serviceInfo.applicationInfo.flags
9740 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9741 minDuration /= 4;
9742 }
9743
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009744 // Any delivered but not yet finished starts should be put back
9745 // on the pending list.
9746 final int N = r.deliveredStarts.size();
9747 if (N > 0) {
9748 for (int i=N-1; i>=0; i--) {
9749 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009750 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009751 if (si.intent == null) {
9752 // We'll generate this again if needed.
9753 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9754 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9755 r.pendingStarts.add(0, si);
9756 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9757 dur *= 2;
9758 if (minDuration < dur) minDuration = dur;
9759 if (resetTime < dur) resetTime = dur;
9760 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009761 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009762 + r.name);
9763 canceled = true;
9764 }
9765 }
9766 r.deliveredStarts.clear();
9767 }
9768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009769 r.totalRestartCount++;
9770 if (r.restartDelay == 0) {
9771 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009772 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009773 } else {
9774 // If it has been a "reasonably long time" since the service
9775 // was started, then reset our restart duration back to
9776 // the beginning, so we don't infinitely increase the duration
9777 // on a service that just occasionally gets killed (which is
9778 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009779 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009781 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009782 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009783 if ((r.serviceInfo.applicationInfo.flags
9784 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9785 // Services in peristent processes will restart much more
9786 // quickly, since they are pretty important. (Think SystemUI).
9787 r.restartDelay += minDuration/2;
9788 } else {
9789 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9790 if (r.restartDelay < minDuration) {
9791 r.restartDelay = minDuration;
9792 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794 }
9795 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009796
9797 r.nextRestartTime = now + r.restartDelay;
9798
9799 // Make sure that we don't end up restarting a bunch of services
9800 // all at the same time.
9801 boolean repeat;
9802 do {
9803 repeat = false;
9804 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9805 ServiceRecord r2 = mRestartingServices.get(i);
9806 if (r2 != r && r.nextRestartTime
9807 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9808 && r.nextRestartTime
9809 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9810 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9811 r.restartDelay = r.nextRestartTime - now;
9812 repeat = true;
9813 break;
9814 }
9815 }
9816 } while (repeat);
9817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009818 if (!mRestartingServices.contains(r)) {
9819 mRestartingServices.add(r);
9820 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009821
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009822 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009823
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009824 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009825 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009826 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009827 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009828 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009829 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 r.shortName, r.restartDelay);
9831
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009832 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833 }
9834
9835 final void performServiceRestartLocked(ServiceRecord r) {
9836 if (!mRestartingServices.contains(r)) {
9837 return;
9838 }
9839 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9840 }
9841
9842 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9843 if (r.restartDelay == 0) {
9844 return false;
9845 }
9846 r.resetRestartCounter();
9847 mRestartingServices.remove(r);
9848 mHandler.removeCallbacks(r.restarter);
9849 return true;
9850 }
9851
9852 private final boolean bringUpServiceLocked(ServiceRecord r,
9853 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009854 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009855 //r.dump(" ");
9856
Dianne Hackborn36124872009-10-08 16:22:03 -07009857 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009858 sendServiceArgsLocked(r, false);
9859 return true;
9860 }
9861
9862 if (!whileRestarting && r.restartDelay > 0) {
9863 // If waiting for a restart, then do nothing.
9864 return true;
9865 }
9866
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009867 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009869 // We are now bringing the service up, so no longer in the
9870 // restarting state.
9871 mRestartingServices.remove(r);
9872
Dianne Hackborne7f97212011-02-24 14:40:20 -08009873 // Service is now being launched, its package can't be stopped.
9874 try {
9875 AppGlobals.getPackageManager().setPackageStoppedState(
9876 r.packageName, false);
9877 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009878 } catch (IllegalArgumentException e) {
9879 Slog.w(TAG, "Failed trying to unstop package "
9880 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009881 }
9882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009883 final String appName = r.processName;
9884 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9885 if (app != null && app.thread != null) {
9886 try {
9887 realStartServiceLocked(r, app);
9888 return true;
9889 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009890 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009891 }
9892
9893 // If a dead object exception was thrown -- fall through to
9894 // restart the application.
9895 }
9896
Dianne Hackborn36124872009-10-08 16:22:03 -07009897 // Not running -- get it started, and enqueue this service record
9898 // to be executed when the app comes up.
9899 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9900 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009901 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009902 + r.appInfo.packageName + "/"
9903 + r.appInfo.uid + " for service "
9904 + r.intent.getIntent() + ": process is bad");
9905 bringDownServiceLocked(r, true);
9906 return false;
9907 }
9908
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009909 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009910 mPendingServices.add(r);
9911 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009913 return true;
9914 }
9915
9916 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009917 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009918 //r.dump(" ");
9919
9920 // Does it still need to run?
9921 if (!force && r.startRequested) {
9922 return;
9923 }
9924 if (r.connections.size() > 0) {
9925 if (!force) {
9926 // XXX should probably keep a count of the number of auto-create
9927 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009928 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009929 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009930 ArrayList<ConnectionRecord> cr = it.next();
9931 for (int i=0; i<cr.size(); i++) {
9932 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9933 return;
9934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009935 }
9936 }
9937 }
9938
9939 // Report to all of the connections that the service is no longer
9940 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009941 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009942 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009943 ArrayList<ConnectionRecord> c = it.next();
9944 for (int i=0; i<c.size(); i++) {
9945 try {
9946 c.get(i).conn.connected(r.name, null);
9947 } catch (Exception e) {
9948 Slog.w(TAG, "Failure disconnecting service " + r.name +
9949 " to connection " + c.get(i).conn.asBinder() +
9950 " (in " + c.get(i).binding.client.processName + ")", e);
9951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009952 }
9953 }
9954 }
9955
9956 // Tell the service that it has been unbound.
9957 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9958 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9959 while (it.hasNext()) {
9960 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009961 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 + ": hasBound=" + ibr.hasBound);
9963 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9964 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009965 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009966 updateOomAdjLocked(r.app);
9967 ibr.hasBound = false;
9968 r.app.thread.scheduleUnbindService(r,
9969 ibr.intent.getIntent());
9970 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009971 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009972 + r.shortName, e);
9973 serviceDoneExecutingLocked(r, true);
9974 }
9975 }
9976 }
9977 }
9978
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009979 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009980 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009981 System.identityHashCode(r), r.shortName,
9982 (r.app != null) ? r.app.pid : -1);
9983
9984 mServices.remove(r.name);
9985 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009986 r.totalRestartCount = 0;
9987 unscheduleServiceRestartLocked(r);
9988
9989 // Also make sure it is not on the pending list.
9990 int N = mPendingServices.size();
9991 for (int i=0; i<N; i++) {
9992 if (mPendingServices.get(i) == r) {
9993 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009994 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009995 i--;
9996 N--;
9997 }
9998 }
9999
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010000 r.cancelNotification();
10001 r.isForeground = false;
10002 r.foregroundId = 0;
10003 r.foregroundNoti = null;
10004
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010005 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070010006 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010007 r.pendingStarts.clear();
10008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010009 if (r.app != null) {
10010 synchronized (r.stats.getBatteryStats()) {
10011 r.stats.stopLaunchedLocked();
10012 }
10013 r.app.services.remove(r);
10014 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010015 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010016 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010017 mStoppingServices.add(r);
10018 updateOomAdjLocked(r.app);
10019 r.app.thread.scheduleStopService(r);
10020 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010021 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010022 + r.shortName, e);
10023 serviceDoneExecutingLocked(r, true);
10024 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010025 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010026 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010027 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010028 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010029 }
10030 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010031 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010032 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010033 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080010034
10035 if (r.bindings.size() > 0) {
10036 r.bindings.clear();
10037 }
10038
10039 if (r.restarter instanceof ServiceRestarter) {
10040 ((ServiceRestarter)r.restarter).setService(null);
10041 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010042 }
10043
10044 ComponentName startServiceLocked(IApplicationThread caller,
10045 Intent service, String resolvedType,
10046 int callingPid, int callingUid) {
10047 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010048 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010049 + " type=" + resolvedType + " args=" + service.getExtras());
10050
10051 if (caller != null) {
10052 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10053 if (callerApp == null) {
10054 throw new SecurityException(
10055 "Unable to find app for caller " + caller
10056 + " (pid=" + Binder.getCallingPid()
10057 + ") when starting service " + service);
10058 }
10059 }
10060
10061 ServiceLookupResult res =
10062 retrieveServiceLocked(service, resolvedType,
10063 callingPid, callingUid);
10064 if (res == null) {
10065 return null;
10066 }
10067 if (res.record == null) {
10068 return new ComponentName("!", res.permission != null
10069 ? res.permission : "private to package");
10070 }
10071 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070010072 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
10073 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010074 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010075 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010076 }
10077 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010078 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010079 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070010080 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010081 r.lastActivity = SystemClock.uptimeMillis();
10082 synchronized (r.stats.getBatteryStats()) {
10083 r.stats.startRunningLocked();
10084 }
10085 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
10086 return new ComponentName("!", "Service process is bad");
10087 }
10088 return r.name;
10089 }
10090 }
10091
10092 public ComponentName startService(IApplicationThread caller, Intent service,
10093 String resolvedType) {
10094 // Refuse possible leaked file descriptors
10095 if (service != null && service.hasFileDescriptors() == true) {
10096 throw new IllegalArgumentException("File descriptors passed in Intent");
10097 }
10098
10099 synchronized(this) {
10100 final int callingPid = Binder.getCallingPid();
10101 final int callingUid = Binder.getCallingUid();
10102 final long origId = Binder.clearCallingIdentity();
10103 ComponentName res = startServiceLocked(caller, service,
10104 resolvedType, callingPid, callingUid);
10105 Binder.restoreCallingIdentity(origId);
10106 return res;
10107 }
10108 }
10109
10110 ComponentName startServiceInPackage(int uid,
10111 Intent service, String resolvedType) {
10112 synchronized(this) {
10113 final long origId = Binder.clearCallingIdentity();
10114 ComponentName res = startServiceLocked(null, service,
10115 resolvedType, -1, uid);
10116 Binder.restoreCallingIdentity(origId);
10117 return res;
10118 }
10119 }
10120
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010121 private void stopServiceLocked(ServiceRecord service) {
10122 synchronized (service.stats.getBatteryStats()) {
10123 service.stats.stopRunningLocked();
10124 }
10125 service.startRequested = false;
10126 service.callStart = false;
10127 bringDownServiceLocked(service, false);
10128 }
10129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010130 public int stopService(IApplicationThread caller, Intent service,
10131 String resolvedType) {
10132 // Refuse possible leaked file descriptors
10133 if (service != null && service.hasFileDescriptors() == true) {
10134 throw new IllegalArgumentException("File descriptors passed in Intent");
10135 }
10136
10137 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010138 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010139 + " type=" + resolvedType);
10140
10141 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10142 if (caller != null && callerApp == null) {
10143 throw new SecurityException(
10144 "Unable to find app for caller " + caller
10145 + " (pid=" + Binder.getCallingPid()
10146 + ") when stopping service " + service);
10147 }
10148
10149 // If this service is active, make sure it is stopped.
10150 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10151 if (r != null) {
10152 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010153 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010154 try {
10155 stopServiceLocked(r.record);
10156 } finally {
10157 Binder.restoreCallingIdentity(origId);
10158 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010159 return 1;
10160 }
10161 return -1;
10162 }
10163 }
10164
10165 return 0;
10166 }
10167
10168 public IBinder peekService(Intent service, String resolvedType) {
10169 // Refuse possible leaked file descriptors
10170 if (service != null && service.hasFileDescriptors() == true) {
10171 throw new IllegalArgumentException("File descriptors passed in Intent");
10172 }
10173
10174 IBinder ret = null;
10175
10176 synchronized(this) {
10177 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10178
10179 if (r != null) {
10180 // r.record is null if findServiceLocked() failed the caller permission check
10181 if (r.record == null) {
10182 throw new SecurityException(
10183 "Permission Denial: Accessing service " + r.record.name
10184 + " from pid=" + Binder.getCallingPid()
10185 + ", uid=" + Binder.getCallingUid()
10186 + " requires " + r.permission);
10187 }
10188 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10189 if (ib != null) {
10190 ret = ib.binder;
10191 }
10192 }
10193 }
10194
10195 return ret;
10196 }
10197
10198 public boolean stopServiceToken(ComponentName className, IBinder token,
10199 int startId) {
10200 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010201 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010202 + " " + token + " startId=" + startId);
10203 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010204 if (r != null) {
10205 if (startId >= 0) {
10206 // Asked to only stop if done with all work. Note that
10207 // to avoid leaks, we will take this as dropping all
10208 // start items up to and including this one.
10209 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10210 if (si != null) {
10211 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010212 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10213 cur.removeUriPermissionsLocked();
10214 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010215 break;
10216 }
10217 }
10218 }
10219
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010220 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010221 return false;
10222 }
10223
10224 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010225 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010226 + " is last, but have " + r.deliveredStarts.size()
10227 + " remaining args");
10228 }
10229 }
10230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010231 synchronized (r.stats.getBatteryStats()) {
10232 r.stats.stopRunningLocked();
10233 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010234 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010235 }
10236 final long origId = Binder.clearCallingIdentity();
10237 bringDownServiceLocked(r, false);
10238 Binder.restoreCallingIdentity(origId);
10239 return true;
10240 }
10241 }
10242 return false;
10243 }
10244
10245 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010246 int id, Notification notification, boolean removeNotification) {
10247 final long origId = Binder.clearCallingIdentity();
10248 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249 synchronized(this) {
10250 ServiceRecord r = findServiceLocked(className, token);
10251 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010252 if (id != 0) {
10253 if (notification == null) {
10254 throw new IllegalArgumentException("null notification");
10255 }
10256 if (r.foregroundId != id) {
10257 r.cancelNotification();
10258 r.foregroundId = id;
10259 }
10260 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10261 r.foregroundNoti = notification;
10262 r.isForeground = true;
10263 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010264 if (r.app != null) {
10265 updateServiceForegroundLocked(r.app, true);
10266 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010267 } else {
10268 if (r.isForeground) {
10269 r.isForeground = false;
10270 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010271 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010272 updateServiceForegroundLocked(r.app, true);
10273 }
10274 }
10275 if (removeNotification) {
10276 r.cancelNotification();
10277 r.foregroundId = 0;
10278 r.foregroundNoti = null;
10279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010280 }
10281 }
10282 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010283 } finally {
10284 Binder.restoreCallingIdentity(origId);
10285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010286 }
10287
10288 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10289 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010290 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010291 if (sr.isForeground) {
10292 anyForeground = true;
10293 break;
10294 }
10295 }
10296 if (anyForeground != proc.foregroundServices) {
10297 proc.foregroundServices = anyForeground;
10298 if (oomAdj) {
10299 updateOomAdjLocked();
10300 }
10301 }
10302 }
10303
10304 public int bindService(IApplicationThread caller, IBinder token,
10305 Intent service, String resolvedType,
10306 IServiceConnection connection, int flags) {
10307 // Refuse possible leaked file descriptors
10308 if (service != null && service.hasFileDescriptors() == true) {
10309 throw new IllegalArgumentException("File descriptors passed in Intent");
10310 }
10311
10312 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010313 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 + " type=" + resolvedType + " conn=" + connection.asBinder()
10315 + " flags=0x" + Integer.toHexString(flags));
10316 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10317 if (callerApp == null) {
10318 throw new SecurityException(
10319 "Unable to find app for caller " + caller
10320 + " (pid=" + Binder.getCallingPid()
10321 + ") when binding service " + service);
10322 }
10323
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010324 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010325 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010326 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010328 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010329 return 0;
10330 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010331 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010332 }
10333
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010334 int clientLabel = 0;
10335 PendingIntent clientIntent = null;
10336
10337 if (callerApp.info.uid == Process.SYSTEM_UID) {
10338 // Hacky kind of thing -- allow system stuff to tell us
10339 // what they are, so we can report this elsewhere for
10340 // others to know why certain services are running.
10341 try {
10342 clientIntent = (PendingIntent)service.getParcelableExtra(
10343 Intent.EXTRA_CLIENT_INTENT);
10344 } catch (RuntimeException e) {
10345 }
10346 if (clientIntent != null) {
10347 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10348 if (clientLabel != 0) {
10349 // There are no useful extras in the intent, trash them.
10350 // System code calling with this stuff just needs to know
10351 // this will happen.
10352 service = service.cloneFilter();
10353 }
10354 }
10355 }
10356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 ServiceLookupResult res =
10358 retrieveServiceLocked(service, resolvedType,
10359 Binder.getCallingPid(), Binder.getCallingUid());
10360 if (res == null) {
10361 return 0;
10362 }
10363 if (res.record == null) {
10364 return -1;
10365 }
10366 ServiceRecord s = res.record;
10367
10368 final long origId = Binder.clearCallingIdentity();
10369
10370 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010371 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010372 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 }
10374
10375 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10376 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010377 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378
10379 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010380 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10381 if (clist == null) {
10382 clist = new ArrayList<ConnectionRecord>();
10383 s.connections.put(binder, clist);
10384 }
10385 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010386 b.connections.add(c);
10387 if (activity != null) {
10388 if (activity.connections == null) {
10389 activity.connections = new HashSet<ConnectionRecord>();
10390 }
10391 activity.connections.add(c);
10392 }
10393 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010394 clist = mServiceConnections.get(binder);
10395 if (clist == null) {
10396 clist = new ArrayList<ConnectionRecord>();
10397 mServiceConnections.put(binder, clist);
10398 }
10399 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010400
10401 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10402 s.lastActivity = SystemClock.uptimeMillis();
10403 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10404 return 0;
10405 }
10406 }
10407
10408 if (s.app != null) {
10409 // This could have made the service more important.
10410 updateOomAdjLocked(s.app);
10411 }
10412
Joe Onorato8a9b2202010-02-26 18:56:32 -080010413 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010414 + ": received=" + b.intent.received
10415 + " apps=" + b.intent.apps.size()
10416 + " doRebind=" + b.intent.doRebind);
10417
10418 if (s.app != null && b.intent.received) {
10419 // Service is already running, so we can immediately
10420 // publish the connection.
10421 try {
10422 c.conn.connected(s.name, b.intent.binder);
10423 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010424 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010425 + " to connection " + c.conn.asBinder()
10426 + " (in " + c.binding.client.processName + ")", e);
10427 }
10428
10429 // If this is the first app connected back to this binding,
10430 // and the service had previously asked to be told when
10431 // rebound, then do so.
10432 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10433 requestServiceBindingLocked(s, b.intent, true);
10434 }
10435 } else if (!b.intent.requested) {
10436 requestServiceBindingLocked(s, b.intent, false);
10437 }
10438
10439 Binder.restoreCallingIdentity(origId);
10440 }
10441
10442 return 1;
10443 }
10444
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010445 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010446 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010447 IBinder binder = c.conn.asBinder();
10448 AppBindRecord b = c.binding;
10449 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010450 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10451 if (clist != null) {
10452 clist.remove(c);
10453 if (clist.size() == 0) {
10454 s.connections.remove(binder);
10455 }
10456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010457 b.connections.remove(c);
10458 if (c.activity != null && c.activity != skipAct) {
10459 if (c.activity.connections != null) {
10460 c.activity.connections.remove(c);
10461 }
10462 }
10463 if (b.client != skipApp) {
10464 b.client.connections.remove(c);
10465 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010466 clist = mServiceConnections.get(binder);
10467 if (clist != null) {
10468 clist.remove(c);
10469 if (clist.size() == 0) {
10470 mServiceConnections.remove(binder);
10471 }
10472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010473
10474 if (b.connections.size() == 0) {
10475 b.intent.apps.remove(b.client);
10476 }
10477
Joe Onorato8a9b2202010-02-26 18:56:32 -080010478 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 + ": shouldUnbind=" + b.intent.hasBound);
10480 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10481 && b.intent.hasBound) {
10482 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010483 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010484 updateOomAdjLocked(s.app);
10485 b.intent.hasBound = false;
10486 // Assume the client doesn't want to know about a rebind;
10487 // we will deal with that later if it asks for one.
10488 b.intent.doRebind = false;
10489 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10490 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010491 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010492 serviceDoneExecutingLocked(s, true);
10493 }
10494 }
10495
10496 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10497 bringDownServiceLocked(s, false);
10498 }
10499 }
10500
10501 public boolean unbindService(IServiceConnection connection) {
10502 synchronized (this) {
10503 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010504 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010505 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10506 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010507 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010508 + connection.asBinder());
10509 return false;
10510 }
10511
10512 final long origId = Binder.clearCallingIdentity();
10513
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010514 while (clist.size() > 0) {
10515 ConnectionRecord r = clist.get(0);
10516 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010517
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010518 if (r.binding.service.app != null) {
10519 // This could have made the service less important.
10520 updateOomAdjLocked(r.binding.service.app);
10521 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010522 }
10523
10524 Binder.restoreCallingIdentity(origId);
10525 }
10526
10527 return true;
10528 }
10529
10530 public void publishService(IBinder token, Intent intent, IBinder service) {
10531 // Refuse possible leaked file descriptors
10532 if (intent != null && intent.hasFileDescriptors() == true) {
10533 throw new IllegalArgumentException("File descriptors passed in Intent");
10534 }
10535
10536 synchronized(this) {
10537 if (!(token instanceof ServiceRecord)) {
10538 throw new IllegalArgumentException("Invalid service token");
10539 }
10540 ServiceRecord r = (ServiceRecord)token;
10541
10542 final long origId = Binder.clearCallingIdentity();
10543
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010544 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010545 + " " + intent + ": " + service);
10546 if (r != null) {
10547 Intent.FilterComparison filter
10548 = new Intent.FilterComparison(intent);
10549 IntentBindRecord b = r.bindings.get(filter);
10550 if (b != null && !b.received) {
10551 b.binder = service;
10552 b.requested = true;
10553 b.received = true;
10554 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010555 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010556 = r.connections.values().iterator();
10557 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010558 ArrayList<ConnectionRecord> clist = it.next();
10559 for (int i=0; i<clist.size(); i++) {
10560 ConnectionRecord c = clist.get(i);
10561 if (!filter.equals(c.binding.intent.intent)) {
10562 if (DEBUG_SERVICE) Slog.v(
10563 TAG, "Not publishing to: " + c);
10564 if (DEBUG_SERVICE) Slog.v(
10565 TAG, "Bound intent: " + c.binding.intent.intent);
10566 if (DEBUG_SERVICE) Slog.v(
10567 TAG, "Published intent: " + intent);
10568 continue;
10569 }
10570 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10571 try {
10572 c.conn.connected(r.name, service);
10573 } catch (Exception e) {
10574 Slog.w(TAG, "Failure sending service " + r.name +
10575 " to connection " + c.conn.asBinder() +
10576 " (in " + c.binding.client.processName + ")", e);
10577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010578 }
10579 }
10580 }
10581 }
10582
10583 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10584
10585 Binder.restoreCallingIdentity(origId);
10586 }
10587 }
10588 }
10589
10590 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10591 // Refuse possible leaked file descriptors
10592 if (intent != null && intent.hasFileDescriptors() == true) {
10593 throw new IllegalArgumentException("File descriptors passed in Intent");
10594 }
10595
10596 synchronized(this) {
10597 if (!(token instanceof ServiceRecord)) {
10598 throw new IllegalArgumentException("Invalid service token");
10599 }
10600 ServiceRecord r = (ServiceRecord)token;
10601
10602 final long origId = Binder.clearCallingIdentity();
10603
10604 if (r != null) {
10605 Intent.FilterComparison filter
10606 = new Intent.FilterComparison(intent);
10607 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010608 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010609 + " at " + b + ": apps="
10610 + (b != null ? b.apps.size() : 0));
10611 if (b != null) {
10612 if (b.apps.size() > 0) {
10613 // Applications have already bound since the last
10614 // unbind, so just rebind right here.
10615 requestServiceBindingLocked(r, b, true);
10616 } else {
10617 // Note to tell the service the next time there is
10618 // a new client.
10619 b.doRebind = true;
10620 }
10621 }
10622
10623 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10624
10625 Binder.restoreCallingIdentity(origId);
10626 }
10627 }
10628 }
10629
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010630 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010631 synchronized(this) {
10632 if (!(token instanceof ServiceRecord)) {
10633 throw new IllegalArgumentException("Invalid service token");
10634 }
10635 ServiceRecord r = (ServiceRecord)token;
10636 boolean inStopping = mStoppingServices.contains(token);
10637 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010638 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010639 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010640 + " with incorrect token: given " + token
10641 + ", expected " + r);
10642 return;
10643 }
10644
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010645 if (type == 1) {
10646 // This is a call from a service start... take care of
10647 // book-keeping.
10648 r.callStart = true;
10649 switch (res) {
10650 case Service.START_STICKY_COMPATIBILITY:
10651 case Service.START_STICKY: {
10652 // We are done with the associated start arguments.
10653 r.findDeliveredStart(startId, true);
10654 // Don't stop if killed.
10655 r.stopIfKilled = false;
10656 break;
10657 }
10658 case Service.START_NOT_STICKY: {
10659 // We are done with the associated start arguments.
10660 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010661 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010662 // There is no more work, and this service
10663 // doesn't want to hang around if killed.
10664 r.stopIfKilled = true;
10665 }
10666 break;
10667 }
10668 case Service.START_REDELIVER_INTENT: {
10669 // We'll keep this item until they explicitly
10670 // call stop for it, but keep track of the fact
10671 // that it was delivered.
10672 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10673 if (si != null) {
10674 si.deliveryCount = 0;
10675 si.doneExecutingCount++;
10676 // Don't stop if killed.
10677 r.stopIfKilled = true;
10678 }
10679 break;
10680 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010681 case Service.START_TASK_REMOVED_COMPLETE: {
10682 // Special processing for onTaskRemoved(). Don't
10683 // impact normal onStartCommand() processing.
10684 r.findDeliveredStart(startId, true);
10685 break;
10686 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010687 default:
10688 throw new IllegalArgumentException(
10689 "Unknown service start result: " + res);
10690 }
10691 if (res == Service.START_STICKY_COMPATIBILITY) {
10692 r.callStart = false;
10693 }
10694 }
10695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010696 final long origId = Binder.clearCallingIdentity();
10697 serviceDoneExecutingLocked(r, inStopping);
10698 Binder.restoreCallingIdentity(origId);
10699 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010700 Slog.w(TAG, "Done executing unknown service from pid "
10701 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010702 }
10703 }
10704 }
10705
10706 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010707 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10708 + ": nesting=" + r.executeNesting
10709 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010710 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010711 r.executeNesting--;
10712 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010713 if (DEBUG_SERVICE) Slog.v(TAG,
10714 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010715 r.app.executingServices.remove(r);
10716 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010717 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10718 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010719 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10720 }
10721 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010722 if (DEBUG_SERVICE) Slog.v(TAG,
10723 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010724 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010725 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010726 }
10727 updateOomAdjLocked(r.app);
10728 }
10729 }
10730
10731 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010732 String anrMessage = null;
10733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010734 synchronized(this) {
10735 if (proc.executingServices.size() == 0 || proc.thread == null) {
10736 return;
10737 }
10738 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10739 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10740 ServiceRecord timeout = null;
10741 long nextTime = 0;
10742 while (it.hasNext()) {
10743 ServiceRecord sr = it.next();
10744 if (sr.executingStart < maxTime) {
10745 timeout = sr;
10746 break;
10747 }
10748 if (sr.executingStart > nextTime) {
10749 nextTime = sr.executingStart;
10750 }
10751 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010752 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010753 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010754 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010755 } else {
10756 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10757 msg.obj = proc;
10758 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10759 }
10760 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010761
10762 if (anrMessage != null) {
10763 appNotResponding(proc, null, null, anrMessage);
10764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 }
10766
10767 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010768 // BACKUP AND RESTORE
10769 // =========================================================
10770
10771 // Cause the target app to be launched if necessary and its backup agent
10772 // instantiated. The backup agent will invoke backupAgentCreated() on the
10773 // activity manager to announce its creation.
10774 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010775 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010776 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10777
10778 synchronized(this) {
10779 // !!! TODO: currently no check here that we're already bound
10780 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10781 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10782 synchronized (stats) {
10783 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10784 }
10785
Dianne Hackborne7f97212011-02-24 14:40:20 -080010786 // Backup agent is now in use, its package can't be stopped.
10787 try {
10788 AppGlobals.getPackageManager().setPackageStoppedState(
10789 app.packageName, false);
10790 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010791 } catch (IllegalArgumentException e) {
10792 Slog.w(TAG, "Failed trying to unstop package "
10793 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010794 }
10795
Christopher Tate181fafa2009-05-14 11:12:14 -070010796 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070010797 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
10798 ? new ComponentName(app.packageName, app.backupAgentName)
10799 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070010800 // startProcessLocked() returns existing proc's record if it's already running
10801 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010802 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010803 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010804 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010805 return false;
10806 }
10807
10808 r.app = proc;
10809 mBackupTarget = r;
10810 mBackupAppName = app.packageName;
10811
Christopher Tate6fa95972009-06-05 18:43:55 -070010812 // Try not to kill the process during backup
10813 updateOomAdjLocked(proc);
10814
Christopher Tate181fafa2009-05-14 11:12:14 -070010815 // If the process is already attached, schedule the creation of the backup agent now.
10816 // If it is not yet live, this will be done when it attaches to the framework.
10817 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010818 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010819 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010820 proc.thread.scheduleCreateBackupAgent(app,
10821 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010822 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010823 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010824 }
10825 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010826 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010827 }
10828 // Invariants: at this point, the target app process exists and the application
10829 // is either already running or in the process of coming up. mBackupTarget and
10830 // mBackupAppName describe the app, so that when it binds back to the AM we
10831 // know that it's scheduled for a backup-agent operation.
10832 }
10833
10834 return true;
10835 }
10836
10837 // A backup agent has just come up
10838 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010839 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010840 + " = " + agent);
10841
10842 synchronized(this) {
10843 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010844 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010845 return;
10846 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010847 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010848
Dianne Hackborn06740692010-09-22 22:46:21 -070010849 long oldIdent = Binder.clearCallingIdentity();
10850 try {
10851 IBackupManager bm = IBackupManager.Stub.asInterface(
10852 ServiceManager.getService(Context.BACKUP_SERVICE));
10853 bm.agentConnected(agentPackageName, agent);
10854 } catch (RemoteException e) {
10855 // can't happen; the backup manager service is local
10856 } catch (Exception e) {
10857 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10858 e.printStackTrace();
10859 } finally {
10860 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010861 }
10862 }
10863
10864 // done with this agent
10865 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010866 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010867 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010868 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010869 return;
10870 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010871
10872 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010873 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010874 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010875 return;
10876 }
10877
Christopher Tate181fafa2009-05-14 11:12:14 -070010878 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010879 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010880 return;
10881 }
10882
Christopher Tate6fa95972009-06-05 18:43:55 -070010883 ProcessRecord proc = mBackupTarget.app;
10884 mBackupTarget = null;
10885 mBackupAppName = null;
10886
10887 // Not backing this app up any more; reset its OOM adjustment
10888 updateOomAdjLocked(proc);
10889
Christopher Tatec7b31e32009-06-10 15:49:30 -070010890 // If the app crashed during backup, 'thread' will be null here
10891 if (proc.thread != null) {
10892 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010893 proc.thread.scheduleDestroyBackupAgent(appInfo,
10894 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070010895 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010896 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010897 e.printStackTrace();
10898 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010899 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010900 }
10901 }
10902 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010903 // BROADCASTS
10904 // =========================================================
10905
Josh Bartel7f208742010-02-25 11:01:44 -060010906 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010907 List cur) {
10908 final ContentResolver resolver = mContext.getContentResolver();
10909 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10910 if (list == null) {
10911 return cur;
10912 }
10913 int N = list.size();
10914 for (int i=0; i<N; i++) {
10915 Intent intent = list.get(i);
10916 if (filter.match(resolver, intent, true, TAG) >= 0) {
10917 if (cur == null) {
10918 cur = new ArrayList<Intent>();
10919 }
10920 cur.add(intent);
10921 }
10922 }
10923 return cur;
10924 }
10925
10926 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010927 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010928 + mBroadcastsScheduled);
10929
10930 if (mBroadcastsScheduled) {
10931 return;
10932 }
10933 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10934 mBroadcastsScheduled = true;
10935 }
10936
10937 public Intent registerReceiver(IApplicationThread caller,
10938 IIntentReceiver receiver, IntentFilter filter, String permission) {
10939 synchronized(this) {
10940 ProcessRecord callerApp = null;
10941 if (caller != null) {
10942 callerApp = getRecordForAppLocked(caller);
10943 if (callerApp == null) {
10944 throw new SecurityException(
10945 "Unable to find app for caller " + caller
10946 + " (pid=" + Binder.getCallingPid()
10947 + ") when registering receiver " + receiver);
10948 }
10949 }
10950
10951 List allSticky = null;
10952
10953 // Look for any matching sticky broadcasts...
10954 Iterator actions = filter.actionsIterator();
10955 if (actions != null) {
10956 while (actions.hasNext()) {
10957 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010958 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010959 }
10960 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010961 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010962 }
10963
10964 // The first sticky in the list is returned directly back to
10965 // the client.
10966 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10967
Joe Onorato8a9b2202010-02-26 18:56:32 -080010968 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 + ": " + sticky);
10970
10971 if (receiver == null) {
10972 return sticky;
10973 }
10974
10975 ReceiverList rl
10976 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10977 if (rl == null) {
10978 rl = new ReceiverList(this, callerApp,
10979 Binder.getCallingPid(),
10980 Binder.getCallingUid(), receiver);
10981 if (rl.app != null) {
10982 rl.app.receivers.add(rl);
10983 } else {
10984 try {
10985 receiver.asBinder().linkToDeath(rl, 0);
10986 } catch (RemoteException e) {
10987 return sticky;
10988 }
10989 rl.linkedToDeath = true;
10990 }
10991 mRegisteredReceivers.put(receiver.asBinder(), rl);
10992 }
10993 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10994 rl.add(bf);
10995 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010996 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010997 }
10998 mReceiverResolver.addFilter(bf);
10999
11000 // Enqueue broadcasts for all existing stickies that match
11001 // this filter.
11002 if (allSticky != null) {
11003 ArrayList receivers = new ArrayList();
11004 receivers.add(bf);
11005
11006 int N = allSticky.size();
11007 for (int i=0; i<N; i++) {
11008 Intent intent = (Intent)allSticky.get(i);
11009 BroadcastRecord r = new BroadcastRecord(intent, null,
11010 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011011 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011012 if (mParallelBroadcasts.size() == 0) {
11013 scheduleBroadcastsLocked();
11014 }
11015 mParallelBroadcasts.add(r);
11016 }
11017 }
11018
11019 return sticky;
11020 }
11021 }
11022
11023 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011024 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011025
11026 boolean doNext = false;
11027
11028 synchronized(this) {
11029 ReceiverList rl
11030 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11031 if (rl != null) {
11032 if (rl.curBroadcast != null) {
11033 BroadcastRecord r = rl.curBroadcast;
11034 doNext = finishReceiverLocked(
11035 receiver.asBinder(), r.resultCode, r.resultData,
11036 r.resultExtras, r.resultAbort, true);
11037 }
11038
11039 if (rl.app != null) {
11040 rl.app.receivers.remove(rl);
11041 }
11042 removeReceiverLocked(rl);
11043 if (rl.linkedToDeath) {
11044 rl.linkedToDeath = false;
11045 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11046 }
11047 }
11048 }
11049
11050 if (!doNext) {
11051 return;
11052 }
11053
11054 final long origId = Binder.clearCallingIdentity();
11055 processNextBroadcast(false);
11056 trimApplications();
11057 Binder.restoreCallingIdentity(origId);
11058 }
11059
11060 void removeReceiverLocked(ReceiverList rl) {
11061 mRegisteredReceivers.remove(rl.receiver.asBinder());
11062 int N = rl.size();
11063 for (int i=0; i<N; i++) {
11064 mReceiverResolver.removeFilter(rl.get(i));
11065 }
11066 }
11067
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011068 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
11069 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11070 ProcessRecord r = mLruProcesses.get(i);
11071 if (r.thread != null) {
11072 try {
11073 r.thread.dispatchPackageBroadcast(cmd, packages);
11074 } catch (RemoteException ex) {
11075 }
11076 }
11077 }
11078 }
11079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080 private final int broadcastIntentLocked(ProcessRecord callerApp,
11081 String callerPackage, Intent intent, String resolvedType,
11082 IIntentReceiver resultTo, int resultCode, String resultData,
11083 Bundle map, String requiredPermission,
11084 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11085 intent = new Intent(intent);
11086
Dianne Hackborne7f97212011-02-24 14:40:20 -080011087 // By default broadcasts do not go to stopped apps.
11088 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
11089
Joe Onorato8a9b2202010-02-26 18:56:32 -080011090 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11092 + " ordered=" + ordered);
11093 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011094 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011095 }
11096
11097 // Handle special intents: if this broadcast is from the package
11098 // manager about a package being removed, we need to remove all of
11099 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011100 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011101 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011102 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11103 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011104 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011105 || uidRemoved) {
11106 if (checkComponentPermission(
11107 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011108 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 == PackageManager.PERMISSION_GRANTED) {
11110 if (uidRemoved) {
11111 final Bundle intentExtras = intent.getExtras();
11112 final int uid = intentExtras != null
11113 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11114 if (uid >= 0) {
11115 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11116 synchronized (bs) {
11117 bs.removeUidStatsLocked(uid);
11118 }
11119 }
11120 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011121 // If resources are unvailble just force stop all
11122 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011123 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011124 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11125 if (list != null && (list.length > 0)) {
11126 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011127 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011128 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011129 sendPackageBroadcastLocked(
11130 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011131 }
11132 } else {
11133 Uri data = intent.getData();
11134 String ssp;
11135 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11136 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11137 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011138 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011139 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011140 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011141 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
11142 new String[] {ssp});
11143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011144 }
11145 }
11146 }
11147 } else {
11148 String msg = "Permission Denial: " + intent.getAction()
11149 + " broadcast from " + callerPackage + " (pid=" + callingPid
11150 + ", uid=" + callingUid + ")"
11151 + " requires "
11152 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011153 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 throw new SecurityException(msg);
11155 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011156
11157 // Special case for adding a package: by default turn on compatibility
11158 // mode.
11159 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
11160 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
11161 Uri data = intent.getData();
11162 String ssp;
11163 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11164 mCompatModePackages.setPackageScreenCompatModeLocked(ssp,
11165 ActivityManager.COMPAT_MODE_ENABLED);
11166 }
11167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011168 }
11169
11170 /*
11171 * If this is the time zone changed action, queue up a message that will reset the timezone
11172 * of all currently running processes. This message will get queued up before the broadcast
11173 * happens.
11174 */
11175 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11176 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11177 }
11178
Robert Greenwalt03595d02010-11-02 14:08:23 -070011179 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
11180 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
11181 }
11182
Robert Greenwalt434203a2010-10-11 16:00:27 -070011183 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
11184 ProxyProperties proxy = intent.getParcelableExtra("proxy");
11185 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
11186 }
11187
Dianne Hackborn854060af2009-07-09 18:14:31 -070011188 /*
11189 * Prevent non-system code (defined here to be non-persistent
11190 * processes) from sending protected broadcasts.
11191 */
11192 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11193 || callingUid == Process.SHELL_UID || callingUid == 0) {
11194 // Always okay.
11195 } else if (callerApp == null || !callerApp.persistent) {
11196 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011197 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070011198 intent.getAction())) {
11199 String msg = "Permission Denial: not allowed to send broadcast "
11200 + intent.getAction() + " from pid="
11201 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011202 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011203 throw new SecurityException(msg);
11204 }
11205 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011206 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011207 return BROADCAST_SUCCESS;
11208 }
11209 }
11210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011211 // Add to the sticky list if requested.
11212 if (sticky) {
11213 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11214 callingPid, callingUid)
11215 != PackageManager.PERMISSION_GRANTED) {
11216 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11217 + callingPid + ", uid=" + callingUid
11218 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011219 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 throw new SecurityException(msg);
11221 }
11222 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011223 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011224 + " and enforce permission " + requiredPermission);
11225 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11226 }
11227 if (intent.getComponent() != null) {
11228 throw new SecurityException(
11229 "Sticky broadcasts can't target a specific component");
11230 }
11231 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11232 if (list == null) {
11233 list = new ArrayList<Intent>();
11234 mStickyBroadcasts.put(intent.getAction(), list);
11235 }
11236 int N = list.size();
11237 int i;
11238 for (i=0; i<N; i++) {
11239 if (intent.filterEquals(list.get(i))) {
11240 // This sticky already exists, replace it.
11241 list.set(i, new Intent(intent));
11242 break;
11243 }
11244 }
11245 if (i >= N) {
11246 list.add(new Intent(intent));
11247 }
11248 }
11249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011250 // Figure out who all will receive this broadcast.
11251 List receivers = null;
11252 List<BroadcastFilter> registeredReceivers = null;
11253 try {
11254 if (intent.getComponent() != null) {
11255 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011256 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011257 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 if (ai != null) {
11259 receivers = new ArrayList();
11260 ResolveInfo ri = new ResolveInfo();
11261 ri.activityInfo = ai;
11262 receivers.add(ri);
11263 }
11264 } else {
11265 // Need to resolve the intent to interested receivers...
11266 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11267 == 0) {
11268 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011269 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011270 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011271 }
Mihai Preda074edef2009-05-18 17:13:31 +020011272 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011273 }
11274 } catch (RemoteException ex) {
11275 // pm is in same process, this will never happen.
11276 }
11277
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011278 final boolean replacePending =
11279 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11280
Joe Onorato8a9b2202010-02-26 18:56:32 -080011281 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011282 + " replacePending=" + replacePending);
11283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011284 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11285 if (!ordered && NR > 0) {
11286 // If we are not serializing this broadcast, then send the
11287 // registered receivers separately so they don't wait for the
11288 // components to be launched.
11289 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11290 callerPackage, callingPid, callingUid, requiredPermission,
11291 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011292 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011293 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011294 TAG, "Enqueueing parallel broadcast " + r
11295 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011296 boolean replaced = false;
11297 if (replacePending) {
11298 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11299 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011300 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011301 "***** DROPPING PARALLEL: " + intent);
11302 mParallelBroadcasts.set(i, r);
11303 replaced = true;
11304 break;
11305 }
11306 }
11307 }
11308 if (!replaced) {
11309 mParallelBroadcasts.add(r);
11310 scheduleBroadcastsLocked();
11311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 registeredReceivers = null;
11313 NR = 0;
11314 }
11315
11316 // Merge into one list.
11317 int ir = 0;
11318 if (receivers != null) {
11319 // A special case for PACKAGE_ADDED: do not allow the package
11320 // being added to see this broadcast. This prevents them from
11321 // using this as a back door to get run as soon as they are
11322 // installed. Maybe in the future we want to have a special install
11323 // broadcast or such for apps, but we'd like to deliberately make
11324 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011325 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011326 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11327 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11328 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011329 Uri data = intent.getData();
11330 if (data != null) {
11331 String pkgName = data.getSchemeSpecificPart();
11332 if (pkgName != null) {
11333 skipPackages = new String[] { pkgName };
11334 }
11335 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011336 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011337 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011338 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011339 if (skipPackages != null && (skipPackages.length > 0)) {
11340 for (String skipPackage : skipPackages) {
11341 if (skipPackage != null) {
11342 int NT = receivers.size();
11343 for (int it=0; it<NT; it++) {
11344 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11345 if (curt.activityInfo.packageName.equals(skipPackage)) {
11346 receivers.remove(it);
11347 it--;
11348 NT--;
11349 }
11350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011351 }
11352 }
11353 }
11354
11355 int NT = receivers != null ? receivers.size() : 0;
11356 int it = 0;
11357 ResolveInfo curt = null;
11358 BroadcastFilter curr = null;
11359 while (it < NT && ir < NR) {
11360 if (curt == null) {
11361 curt = (ResolveInfo)receivers.get(it);
11362 }
11363 if (curr == null) {
11364 curr = registeredReceivers.get(ir);
11365 }
11366 if (curr.getPriority() >= curt.priority) {
11367 // Insert this broadcast record into the final list.
11368 receivers.add(it, curr);
11369 ir++;
11370 curr = null;
11371 it++;
11372 NT++;
11373 } else {
11374 // Skip to the next ResolveInfo in the final list.
11375 it++;
11376 curt = null;
11377 }
11378 }
11379 }
11380 while (ir < NR) {
11381 if (receivers == null) {
11382 receivers = new ArrayList();
11383 }
11384 receivers.add(registeredReceivers.get(ir));
11385 ir++;
11386 }
11387
11388 if ((receivers != null && receivers.size() > 0)
11389 || resultTo != null) {
11390 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11391 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011392 receivers, resultTo, resultCode, resultData, map, ordered,
11393 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011394 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011395 TAG, "Enqueueing ordered broadcast " + r
11396 + ": prev had " + mOrderedBroadcasts.size());
11397 if (DEBUG_BROADCAST) {
11398 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011399 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011400 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011401 boolean replaced = false;
11402 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011403 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011404 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011405 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011406 "***** DROPPING ORDERED: " + intent);
11407 mOrderedBroadcasts.set(i, r);
11408 replaced = true;
11409 break;
11410 }
11411 }
11412 }
11413 if (!replaced) {
11414 mOrderedBroadcasts.add(r);
11415 scheduleBroadcastsLocked();
11416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011417 }
11418
11419 return BROADCAST_SUCCESS;
11420 }
11421
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011422 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011423 // Refuse possible leaked file descriptors
11424 if (intent != null && intent.hasFileDescriptors() == true) {
11425 throw new IllegalArgumentException("File descriptors passed in Intent");
11426 }
11427
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011428 int flags = intent.getFlags();
11429
11430 if (!mProcessesReady) {
11431 // if the caller really truly claims to know what they're doing, go
11432 // ahead and allow the broadcast without launching any receivers
11433 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11434 intent = new Intent(intent);
11435 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11436 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11437 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11438 + " before boot completion");
11439 throw new IllegalStateException("Cannot broadcast before boot completed");
11440 }
11441 }
11442
11443 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11444 throw new IllegalArgumentException(
11445 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11446 }
11447
11448 return intent;
11449 }
11450
11451 public final int broadcastIntent(IApplicationThread caller,
11452 Intent intent, String resolvedType, IIntentReceiver resultTo,
11453 int resultCode, String resultData, Bundle map,
11454 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011455 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011456 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011458 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11459 final int callingPid = Binder.getCallingPid();
11460 final int callingUid = Binder.getCallingUid();
11461 final long origId = Binder.clearCallingIdentity();
11462 int res = broadcastIntentLocked(callerApp,
11463 callerApp != null ? callerApp.info.packageName : null,
11464 intent, resolvedType, resultTo,
11465 resultCode, resultData, map, requiredPermission, serialized,
11466 sticky, callingPid, callingUid);
11467 Binder.restoreCallingIdentity(origId);
11468 return res;
11469 }
11470 }
11471
11472 int broadcastIntentInPackage(String packageName, int uid,
11473 Intent intent, String resolvedType, IIntentReceiver resultTo,
11474 int resultCode, String resultData, Bundle map,
11475 String requiredPermission, boolean serialized, boolean sticky) {
11476 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011477 intent = verifyBroadcastLocked(intent);
11478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011479 final long origId = Binder.clearCallingIdentity();
11480 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11481 resultTo, resultCode, resultData, map, requiredPermission,
11482 serialized, sticky, -1, uid);
11483 Binder.restoreCallingIdentity(origId);
11484 return res;
11485 }
11486 }
11487
11488 public final void unbroadcastIntent(IApplicationThread caller,
11489 Intent intent) {
11490 // Refuse possible leaked file descriptors
11491 if (intent != null && intent.hasFileDescriptors() == true) {
11492 throw new IllegalArgumentException("File descriptors passed in Intent");
11493 }
11494
11495 synchronized(this) {
11496 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11497 != PackageManager.PERMISSION_GRANTED) {
11498 String msg = "Permission Denial: unbroadcastIntent() from pid="
11499 + Binder.getCallingPid()
11500 + ", uid=" + Binder.getCallingUid()
11501 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011502 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503 throw new SecurityException(msg);
11504 }
11505 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11506 if (list != null) {
11507 int N = list.size();
11508 int i;
11509 for (i=0; i<N; i++) {
11510 if (intent.filterEquals(list.get(i))) {
11511 list.remove(i);
11512 break;
11513 }
11514 }
11515 }
11516 }
11517 }
11518
11519 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11520 String resultData, Bundle resultExtras, boolean resultAbort,
11521 boolean explicit) {
11522 if (mOrderedBroadcasts.size() == 0) {
11523 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011524 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011525 }
11526 return false;
11527 }
11528 BroadcastRecord r = mOrderedBroadcasts.get(0);
11529 if (r.receiver == null) {
11530 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011531 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011532 }
11533 return false;
11534 }
11535 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011536 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011537 return false;
11538 }
11539 int state = r.state;
11540 r.state = r.IDLE;
11541 if (state == r.IDLE) {
11542 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011543 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011544 }
11545 }
11546 r.receiver = null;
11547 r.intent.setComponent(null);
11548 if (r.curApp != null) {
11549 r.curApp.curReceiver = null;
11550 }
11551 if (r.curFilter != null) {
11552 r.curFilter.receiverList.curBroadcast = null;
11553 }
11554 r.curFilter = null;
11555 r.curApp = null;
11556 r.curComponent = null;
11557 r.curReceiver = null;
11558 mPendingBroadcast = null;
11559
11560 r.resultCode = resultCode;
11561 r.resultData = resultData;
11562 r.resultExtras = resultExtras;
11563 r.resultAbort = resultAbort;
11564
11565 // We will process the next receiver right now if this is finishing
11566 // an app receiver (which is always asynchronous) or after we have
11567 // come back from calling a receiver.
11568 return state == BroadcastRecord.APP_RECEIVE
11569 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11570 }
11571
11572 public void finishReceiver(IBinder who, int resultCode, String resultData,
11573 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011574 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011575
11576 // Refuse possible leaked file descriptors
11577 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11578 throw new IllegalArgumentException("File descriptors passed in Bundle");
11579 }
11580
11581 boolean doNext;
11582
11583 final long origId = Binder.clearCallingIdentity();
11584
11585 synchronized(this) {
11586 doNext = finishReceiverLocked(
11587 who, resultCode, resultData, resultExtras, resultAbort, true);
11588 }
11589
11590 if (doNext) {
11591 processNextBroadcast(false);
11592 }
11593 trimApplications();
11594
11595 Binder.restoreCallingIdentity(origId);
11596 }
11597
Jeff Brown4d94a762010-09-23 11:33:28 -070011598 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011599 if (r.nextReceiver > 0) {
11600 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11601 if (curReceiver instanceof BroadcastFilter) {
11602 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011603 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604 System.identityHashCode(r),
11605 r.intent.getAction(),
11606 r.nextReceiver - 1,
11607 System.identityHashCode(bf));
11608 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011609 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011610 System.identityHashCode(r),
11611 r.intent.getAction(),
11612 r.nextReceiver - 1,
11613 ((ResolveInfo)curReceiver).toString());
11614 }
11615 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011616 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011617 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011618 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011619 System.identityHashCode(r),
11620 r.intent.getAction(),
11621 r.nextReceiver,
11622 "NONE");
11623 }
11624 }
11625
Jeff Brown4d94a762010-09-23 11:33:28 -070011626 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11627 if (! mPendingBroadcastTimeoutMessage) {
11628 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11629 mHandler.sendMessageAtTime(msg, timeoutTime);
11630 mPendingBroadcastTimeoutMessage = true;
11631 }
11632 }
11633
11634 private final void cancelBroadcastTimeoutLocked() {
11635 if (mPendingBroadcastTimeoutMessage) {
11636 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11637 mPendingBroadcastTimeoutMessage = false;
11638 }
11639 }
11640
11641 private final void broadcastTimeoutLocked(boolean fromMsg) {
11642 if (fromMsg) {
11643 mPendingBroadcastTimeoutMessage = false;
11644 }
11645
11646 if (mOrderedBroadcasts.size() == 0) {
11647 return;
11648 }
11649
11650 long now = SystemClock.uptimeMillis();
11651 BroadcastRecord r = mOrderedBroadcasts.get(0);
11652 if (fromMsg) {
11653 if (mDidDexOpt) {
11654 // Delay timeouts until dexopt finishes.
11655 mDidDexOpt = false;
11656 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11657 setBroadcastTimeoutLocked(timeoutTime);
11658 return;
11659 }
11660 if (! mProcessesReady) {
11661 // Only process broadcast timeouts if the system is ready. That way
11662 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11663 // to do heavy lifting for system up.
11664 return;
11665 }
11666
11667 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11668 if (timeoutTime > now) {
11669 // We can observe premature timeouts because we do not cancel and reset the
11670 // broadcast timeout message after each receiver finishes. Instead, we set up
11671 // an initial timeout then kick it down the road a little further as needed
11672 // when it expires.
11673 if (DEBUG_BROADCAST) Slog.v(TAG,
11674 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11675 + timeoutTime);
11676 setBroadcastTimeoutLocked(timeoutTime);
11677 return;
11678 }
11679 }
11680
11681 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11682 + ", started " + (now - r.receiverTime) + "ms ago");
11683 r.receiverTime = now;
11684 r.anrCount++;
11685
11686 // Current receiver has passed its expiration date.
11687 if (r.nextReceiver <= 0) {
11688 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11689 return;
11690 }
11691
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011692 ProcessRecord app = null;
11693 String anrMessage = null;
11694
Jeff Brown4d94a762010-09-23 11:33:28 -070011695 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11696 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11697 logBroadcastReceiverDiscardLocked(r);
11698 if (curReceiver instanceof BroadcastFilter) {
11699 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11700 if (bf.receiverList.pid != 0
11701 && bf.receiverList.pid != MY_PID) {
11702 synchronized (this.mPidsSelfLocked) {
11703 app = this.mPidsSelfLocked.get(
11704 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011707 } else {
11708 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011709 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011710
Jeff Brown4d94a762010-09-23 11:33:28 -070011711 if (app != null) {
11712 anrMessage = "Broadcast of " + r.intent.toString();
11713 }
11714
11715 if (mPendingBroadcast == r) {
11716 mPendingBroadcast = null;
11717 }
11718
11719 // Move on to the next receiver.
11720 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11721 r.resultExtras, r.resultAbort, true);
11722 scheduleBroadcastsLocked();
11723
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011724 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011725 // Post the ANR to the handler since we do not want to process ANRs while
11726 // potentially holding our lock.
11727 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011729 }
11730
11731 private final void processCurBroadcastLocked(BroadcastRecord r,
11732 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011733 if (DEBUG_BROADCAST) Slog.v(TAG,
11734 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011735 if (app.thread == null) {
11736 throw new RemoteException();
11737 }
11738 r.receiver = app.thread.asBinder();
11739 r.curApp = app;
11740 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011741 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011742
11743 // Tell the application to launch this receiver.
11744 r.intent.setComponent(r.curComponent);
11745
11746 boolean started = false;
11747 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011748 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011749 "Delivering to component " + r.curComponent
11750 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011751 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011752 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011753 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011754 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011755 if (DEBUG_BROADCAST) Slog.v(TAG,
11756 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011757 started = true;
11758 } finally {
11759 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011760 if (DEBUG_BROADCAST) Slog.v(TAG,
11761 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011762 r.receiver = null;
11763 r.curApp = null;
11764 app.curReceiver = null;
11765 }
11766 }
11767
11768 }
11769
Jeff Brown4d94a762010-09-23 11:33:28 -070011770 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011771 Intent intent, int resultCode, String data, Bundle extras,
11772 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011773 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011774 if (app != null && app.thread != null) {
11775 // If we have an app thread, do the call through that so it is
11776 // correctly ordered with other one-way calls.
11777 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011778 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011780 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011781 }
11782 }
11783
Jeff Brown4d94a762010-09-23 11:33:28 -070011784 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785 BroadcastFilter filter, boolean ordered) {
11786 boolean skip = false;
11787 if (filter.requiredPermission != null) {
11788 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011789 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011790 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011791 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011792 + r.intent.toString()
11793 + " from " + r.callerPackage + " (pid="
11794 + r.callingPid + ", uid=" + r.callingUid + ")"
11795 + " requires " + filter.requiredPermission
11796 + " due to registered receiver " + filter);
11797 skip = true;
11798 }
11799 }
11800 if (r.requiredPermission != null) {
11801 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011802 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011803 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011804 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011805 + r.intent.toString()
11806 + " to " + filter.receiverList.app
11807 + " (pid=" + filter.receiverList.pid
11808 + ", uid=" + filter.receiverList.uid + ")"
11809 + " requires " + r.requiredPermission
11810 + " due to sender " + r.callerPackage
11811 + " (uid " + r.callingUid + ")");
11812 skip = true;
11813 }
11814 }
11815
11816 if (!skip) {
11817 // If this is not being sent as an ordered broadcast, then we
11818 // don't want to touch the fields that keep track of the current
11819 // state of ordered broadcasts.
11820 if (ordered) {
11821 r.receiver = filter.receiverList.receiver.asBinder();
11822 r.curFilter = filter;
11823 filter.receiverList.curBroadcast = r;
11824 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011825 if (filter.receiverList.app != null) {
11826 // Bump hosting application to no longer be in background
11827 // scheduling class. Note that we can't do that if there
11828 // isn't an app... but we can only be in that case for
11829 // things that directly call the IActivityManager API, which
11830 // are already core system stuff so don't matter for this.
11831 r.curApp = filter.receiverList.app;
11832 filter.receiverList.app.curReceiver = r;
11833 updateOomAdjLocked();
11834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011835 }
11836 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011837 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011838 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011839 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011840 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011841 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011842 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011843 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011844 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011845 if (ordered) {
11846 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11847 }
11848 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011849 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011850 if (ordered) {
11851 r.receiver = null;
11852 r.curFilter = null;
11853 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011854 if (filter.receiverList.app != null) {
11855 filter.receiverList.app.curReceiver = null;
11856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011857 }
11858 }
11859 }
11860 }
11861
Dianne Hackborn12527f92009-11-11 17:39:50 -080011862 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11863 if (r.callingUid < 0) {
11864 // This was from a registerReceiver() call; ignore it.
11865 return;
11866 }
11867 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11868 MAX_BROADCAST_HISTORY-1);
11869 r.finishTime = SystemClock.uptimeMillis();
11870 mBroadcastHistory[0] = r;
11871 }
11872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011873 private final void processNextBroadcast(boolean fromMsg) {
11874 synchronized(this) {
11875 BroadcastRecord r;
11876
Joe Onorato8a9b2202010-02-26 18:56:32 -080011877 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011878 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011879 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011880
11881 updateCpuStats();
11882
11883 if (fromMsg) {
11884 mBroadcastsScheduled = false;
11885 }
11886
11887 // First, deliver any non-serialized broadcasts right away.
11888 while (mParallelBroadcasts.size() > 0) {
11889 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011890 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011891 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011892 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011893 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011894 for (int i=0; i<N; i++) {
11895 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011896 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011897 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011898 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011899 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011900 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011901 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011902 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011903 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011904 }
11905
11906 // Now take care of the next serialized one...
11907
11908 // If we are waiting for a process to come up to handle the next
11909 // broadcast, then do nothing at this point. Just in case, we
11910 // check that the process we're waiting for still exists.
11911 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011912 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011913 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011914 + mPendingBroadcast.curApp);
11915 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011916
11917 boolean isDead;
11918 synchronized (mPidsSelfLocked) {
11919 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11920 }
11921 if (!isDead) {
11922 // It's still alive, so keep waiting
11923 return;
11924 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011925 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011926 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011927 mPendingBroadcast.state = BroadcastRecord.IDLE;
11928 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011929 mPendingBroadcast = null;
11930 }
11931 }
11932
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011933 boolean looped = false;
11934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011935 do {
11936 if (mOrderedBroadcasts.size() == 0) {
11937 // No more broadcasts pending, so all done!
11938 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011939 if (looped) {
11940 // If we had finished the last ordered broadcast, then
11941 // make sure all processes have correct oom and sched
11942 // adjustments.
11943 updateOomAdjLocked();
11944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011945 return;
11946 }
11947 r = mOrderedBroadcasts.get(0);
11948 boolean forceReceive = false;
11949
11950 // Ensure that even if something goes awry with the timeout
11951 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011952 // and continue to make progress.
11953 //
11954 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011955 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011956 // one time heavy lifting after system upgrades and can take
11957 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011958 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011959 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011960 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011961 if ((numReceivers > 0) &&
11962 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011963 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011964 + " now=" + now
11965 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011966 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011967 + " intent=" + r.intent
11968 + " numReceivers=" + numReceivers
11969 + " nextReceiver=" + r.nextReceiver
11970 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011971 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011972 forceReceive = true;
11973 r.state = BroadcastRecord.IDLE;
11974 }
11975 }
11976
11977 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011978 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011979 "processNextBroadcast() called when not idle (state="
11980 + r.state + ")");
11981 return;
11982 }
11983
11984 if (r.receivers == null || r.nextReceiver >= numReceivers
11985 || r.resultAbort || forceReceive) {
11986 // No more receivers for this broadcast! Send the final
11987 // result if requested...
11988 if (r.resultTo != null) {
11989 try {
11990 if (DEBUG_BROADCAST) {
11991 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011992 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011993 + " seq=" + seq + " app=" + r.callerApp);
11994 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011995 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011996 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011997 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011998 // Set this to null so that the reference
11999 // (local and remote) isnt kept in the mBroadcastHistory.
12000 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012001 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012002 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012003 }
12004 }
12005
Joe Onorato8a9b2202010-02-26 18:56:32 -080012006 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070012007 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012008
Joe Onorato8a9b2202010-02-26 18:56:32 -080012009 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012010 + r);
12011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012012 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012013 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012014 mOrderedBroadcasts.remove(0);
12015 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012016 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 continue;
12018 }
12019 } while (r == null);
12020
12021 // Get the next receiver...
12022 int recIdx = r.nextReceiver++;
12023
12024 // Keep track of when this receiver started, and make sure there
12025 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012026 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012027 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012028 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012029
Joe Onorato8a9b2202010-02-26 18:56:32 -080012030 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012031 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012032 }
12033 if (! mPendingBroadcastTimeoutMessage) {
12034 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012035 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070012036 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
12037 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012038 }
12039
12040 Object nextReceiver = r.receivers.get(recIdx);
12041 if (nextReceiver instanceof BroadcastFilter) {
12042 // Simple case: this is a registered receiver who gets
12043 // a direct call.
12044 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012045 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012046 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012047 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012048 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012049 if (r.receiver == null || !r.ordered) {
12050 // The receiver has already finished, so schedule to
12051 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012052 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
12053 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012054 r.state = BroadcastRecord.IDLE;
12055 scheduleBroadcastsLocked();
12056 }
12057 return;
12058 }
12059
12060 // Hard case: need to instantiate the receiver, possibly
12061 // starting its application process to host it.
12062
12063 ResolveInfo info =
12064 (ResolveInfo)nextReceiver;
12065
12066 boolean skip = false;
12067 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012068 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
12069 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012070 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012071 if (!info.activityInfo.exported) {
12072 Slog.w(TAG, "Permission Denial: broadcasting "
12073 + r.intent.toString()
12074 + " from " + r.callerPackage + " (pid=" + r.callingPid
12075 + ", uid=" + r.callingUid + ")"
12076 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
12077 + " due to receiver " + info.activityInfo.packageName
12078 + "/" + info.activityInfo.name);
12079 } else {
12080 Slog.w(TAG, "Permission Denial: broadcasting "
12081 + r.intent.toString()
12082 + " from " + r.callerPackage + " (pid=" + r.callingPid
12083 + ", uid=" + r.callingUid + ")"
12084 + " requires " + info.activityInfo.permission
12085 + " due to receiver " + info.activityInfo.packageName
12086 + "/" + info.activityInfo.name);
12087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012088 skip = true;
12089 }
12090 if (r.callingUid != Process.SYSTEM_UID &&
12091 r.requiredPermission != null) {
12092 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012093 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012094 checkPermission(r.requiredPermission,
12095 info.activityInfo.applicationInfo.packageName);
12096 } catch (RemoteException e) {
12097 perm = PackageManager.PERMISSION_DENIED;
12098 }
12099 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012100 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012101 + r.intent + " to "
12102 + info.activityInfo.applicationInfo.packageName
12103 + " requires " + r.requiredPermission
12104 + " due to sender " + r.callerPackage
12105 + " (uid " + r.callingUid + ")");
12106 skip = true;
12107 }
12108 }
12109 if (r.curApp != null && r.curApp.crashing) {
12110 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012111 if (DEBUG_BROADCAST) Slog.v(TAG,
12112 "Skipping deliver ordered " + r + " to " + r.curApp
12113 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012114 skip = true;
12115 }
12116
12117 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012118 if (DEBUG_BROADCAST) Slog.v(TAG,
12119 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012120 r.receiver = null;
12121 r.curFilter = null;
12122 r.state = BroadcastRecord.IDLE;
12123 scheduleBroadcastsLocked();
12124 return;
12125 }
12126
12127 r.state = BroadcastRecord.APP_RECEIVE;
12128 String targetProcess = info.activityInfo.processName;
12129 r.curComponent = new ComponentName(
12130 info.activityInfo.applicationInfo.packageName,
12131 info.activityInfo.name);
12132 r.curReceiver = info.activityInfo;
12133
Dianne Hackborne7f97212011-02-24 14:40:20 -080012134 // Broadcast is being executed, its package can't be stopped.
12135 try {
12136 AppGlobals.getPackageManager().setPackageStoppedState(
12137 r.curComponent.getPackageName(), false);
12138 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012139 } catch (IllegalArgumentException e) {
12140 Slog.w(TAG, "Failed trying to unstop package "
12141 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012142 }
12143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012144 // Is this receiver's application already running?
12145 ProcessRecord app = getProcessRecordLocked(targetProcess,
12146 info.activityInfo.applicationInfo.uid);
12147 if (app != null && app.thread != null) {
12148 try {
12149 processCurBroadcastLocked(r, app);
12150 return;
12151 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012152 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012153 + r.curComponent, e);
12154 }
12155
12156 // If a dead object exception was thrown -- fall through to
12157 // restart the application.
12158 }
12159
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012160 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012161 if (DEBUG_BROADCAST) Slog.v(TAG,
12162 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012163 if ((r.curApp=startProcessLocked(targetProcess,
12164 info.activityInfo.applicationInfo, true,
12165 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012166 "broadcast", r.curComponent,
12167 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12168 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012169 // Ah, this recipient is unavailable. Finish it if necessary,
12170 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012171 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012172 + info.activityInfo.applicationInfo.packageName + "/"
12173 + info.activityInfo.applicationInfo.uid + " for broadcast "
12174 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070012175 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012176 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12177 r.resultExtras, r.resultAbort, true);
12178 scheduleBroadcastsLocked();
12179 r.state = BroadcastRecord.IDLE;
12180 return;
12181 }
12182
12183 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012184 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012185 }
12186 }
12187
12188 // =========================================================
12189 // INSTRUMENTATION
12190 // =========================================================
12191
12192 public boolean startInstrumentation(ComponentName className,
12193 String profileFile, int flags, Bundle arguments,
12194 IInstrumentationWatcher watcher) {
12195 // Refuse possible leaked file descriptors
12196 if (arguments != null && arguments.hasFileDescriptors()) {
12197 throw new IllegalArgumentException("File descriptors passed in Bundle");
12198 }
12199
12200 synchronized(this) {
12201 InstrumentationInfo ii = null;
12202 ApplicationInfo ai = null;
12203 try {
12204 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012205 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012206 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012207 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012208 } catch (PackageManager.NameNotFoundException e) {
12209 }
12210 if (ii == null) {
12211 reportStartInstrumentationFailure(watcher, className,
12212 "Unable to find instrumentation info for: " + className);
12213 return false;
12214 }
12215 if (ai == null) {
12216 reportStartInstrumentationFailure(watcher, className,
12217 "Unable to find instrumentation target package: " + ii.targetPackage);
12218 return false;
12219 }
12220
12221 int match = mContext.getPackageManager().checkSignatures(
12222 ii.targetPackage, ii.packageName);
12223 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12224 String msg = "Permission Denial: starting instrumentation "
12225 + className + " from pid="
12226 + Binder.getCallingPid()
12227 + ", uid=" + Binder.getCallingPid()
12228 + " not allowed because package " + ii.packageName
12229 + " does not have a signature matching the target "
12230 + ii.targetPackage;
12231 reportStartInstrumentationFailure(watcher, className, msg);
12232 throw new SecurityException(msg);
12233 }
12234
12235 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012236 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012237 ProcessRecord app = addAppLocked(ai);
12238 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012239 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012240 app.instrumentationProfileFile = profileFile;
12241 app.instrumentationArguments = arguments;
12242 app.instrumentationWatcher = watcher;
12243 app.instrumentationResultClass = className;
12244 Binder.restoreCallingIdentity(origId);
12245 }
12246
12247 return true;
12248 }
12249
12250 /**
12251 * Report errors that occur while attempting to start Instrumentation. Always writes the
12252 * error to the logs, but if somebody is watching, send the report there too. This enables
12253 * the "am" command to report errors with more information.
12254 *
12255 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12256 * @param cn The component name of the instrumentation.
12257 * @param report The error report.
12258 */
12259 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12260 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012261 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012262 try {
12263 if (watcher != null) {
12264 Bundle results = new Bundle();
12265 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12266 results.putString("Error", report);
12267 watcher.instrumentationStatus(cn, -1, results);
12268 }
12269 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012270 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012271 }
12272 }
12273
12274 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12275 if (app.instrumentationWatcher != null) {
12276 try {
12277 // NOTE: IInstrumentationWatcher *must* be oneway here
12278 app.instrumentationWatcher.instrumentationFinished(
12279 app.instrumentationClass,
12280 resultCode,
12281 results);
12282 } catch (RemoteException e) {
12283 }
12284 }
12285 app.instrumentationWatcher = null;
12286 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012287 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012288 app.instrumentationProfileFile = null;
12289 app.instrumentationArguments = null;
12290
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012291 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012292 }
12293
12294 public void finishInstrumentation(IApplicationThread target,
12295 int resultCode, Bundle results) {
12296 // Refuse possible leaked file descriptors
12297 if (results != null && results.hasFileDescriptors()) {
12298 throw new IllegalArgumentException("File descriptors passed in Intent");
12299 }
12300
12301 synchronized(this) {
12302 ProcessRecord app = getRecordForAppLocked(target);
12303 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012304 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012305 return;
12306 }
12307 final long origId = Binder.clearCallingIdentity();
12308 finishInstrumentationLocked(app, resultCode, results);
12309 Binder.restoreCallingIdentity(origId);
12310 }
12311 }
12312
12313 // =========================================================
12314 // CONFIGURATION
12315 // =========================================================
12316
12317 public ConfigurationInfo getDeviceConfigurationInfo() {
12318 ConfigurationInfo config = new ConfigurationInfo();
12319 synchronized (this) {
12320 config.reqTouchScreen = mConfiguration.touchscreen;
12321 config.reqKeyboardType = mConfiguration.keyboard;
12322 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012323 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12324 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012325 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12326 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012327 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12328 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012329 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12330 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012331 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012332 }
12333 return config;
12334 }
12335
12336 public Configuration getConfiguration() {
12337 Configuration ci;
12338 synchronized(this) {
12339 ci = new Configuration(mConfiguration);
12340 }
12341 return ci;
12342 }
12343
12344 public void updateConfiguration(Configuration values) {
12345 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12346 "updateConfiguration()");
12347
12348 synchronized(this) {
12349 if (values == null && mWindowManager != null) {
12350 // sentinel: fetch the current configuration from the window manager
12351 values = mWindowManager.computeNewConfiguration();
12352 }
12353
12354 final long origId = Binder.clearCallingIdentity();
12355 updateConfigurationLocked(values, null);
12356 Binder.restoreCallingIdentity(origId);
12357 }
12358 }
12359
12360 /**
12361 * Do either or both things: (1) change the current configuration, and (2)
12362 * make sure the given activity is running with the (now) current
12363 * configuration. Returns true if the activity has been left running, or
12364 * false if <var>starting</var> is being destroyed to match the new
12365 * configuration.
12366 */
12367 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012368 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012369 int changes = 0;
12370
12371 boolean kept = true;
12372
12373 if (values != null) {
12374 Configuration newConfig = new Configuration(mConfiguration);
12375 changes = newConfig.updateFrom(values);
12376 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012377 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012378 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012379 }
12380
Doug Zongker2bec3d42009-12-04 12:52:44 -080012381 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012382
12383 if (values.locale != null) {
12384 saveLocaleLocked(values.locale,
12385 !values.locale.equals(mConfiguration.locale),
12386 values.userSetLocale);
12387 }
12388
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012389 mConfigurationSeq++;
12390 if (mConfigurationSeq <= 0) {
12391 mConfigurationSeq = 1;
12392 }
12393 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012394 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012395 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012396
12397 AttributeCache ac = AttributeCache.instance();
12398 if (ac != null) {
12399 ac.updateConfiguration(mConfiguration);
12400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012401
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012402 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
12403 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12404 msg.obj = new Configuration(mConfiguration);
12405 mHandler.sendMessage(msg);
12406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012407
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012408 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12409 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012410 try {
12411 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012412 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012413 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012414 app.thread.scheduleConfigurationChanged(mConfiguration);
12415 }
12416 } catch (Exception e) {
12417 }
12418 }
12419 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012420 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12421 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012422 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12423 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012424 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12425 broadcastIntentLocked(null, null,
12426 new Intent(Intent.ACTION_LOCALE_CHANGED),
12427 null, null, 0, null, null,
12428 null, false, false, MY_PID, Process.SYSTEM_UID);
12429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012430 }
12431 }
12432
12433 if (changes != 0 && starting == null) {
12434 // If the configuration changed, and the caller is not already
12435 // in the process of starting an activity, then find the top
12436 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012437 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012438 }
12439
12440 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012441 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012442 // And we need to make sure at this point that all other activities
12443 // are made visible with the correct configuration.
12444 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012445 }
12446
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012447 if (values != null && mWindowManager != null) {
12448 mWindowManager.setNewConfiguration(mConfiguration);
12449 }
12450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012451 return kept;
12452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012453
12454 /**
12455 * Save the locale. You must be inside a synchronized (this) block.
12456 */
12457 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12458 if(isDiff) {
12459 SystemProperties.set("user.language", l.getLanguage());
12460 SystemProperties.set("user.region", l.getCountry());
12461 }
12462
12463 if(isPersist) {
12464 SystemProperties.set("persist.sys.language", l.getLanguage());
12465 SystemProperties.set("persist.sys.country", l.getCountry());
12466 SystemProperties.set("persist.sys.localevar", l.getVariant());
12467 }
12468 }
12469
12470 // =========================================================
12471 // LIFETIME MANAGEMENT
12472 // =========================================================
12473
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012474 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12475 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012476 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012477 // This adjustment has already been computed. If we are calling
12478 // from the top, we may have already computed our adjustment with
12479 // an earlier hidden adjustment that isn't really for us... if
12480 // so, use the new hidden adjustment.
12481 if (!recursed && app.hidden) {
12482 app.curAdj = hiddenAdj;
12483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012484 return app.curAdj;
12485 }
12486
12487 if (app.thread == null) {
12488 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012489 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012490 return (app.curAdj=EMPTY_APP_ADJ);
12491 }
12492
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012493 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12494 // The max adjustment doesn't allow this app to be anything
12495 // below foreground, so it is not worth doing work for it.
12496 app.adjType = "fixed";
12497 app.adjSeq = mAdjSeq;
12498 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012499 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012500 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12501 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012502 }
12503
12504 final boolean hadForegroundActivities = app.foregroundActivities;
12505
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012506 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012507 app.adjSource = null;
12508 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012509 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012510 app.empty = false;
12511 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012512 app.foregroundActivities = false;
12513
12514 final int activitiesSize = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012515
The Android Open Source Project4df24232009-03-05 14:34:35 -080012516 // Determine the importance of the process, starting with most
12517 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012518 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012519 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012520 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012521 // The last app on the list is the foreground app.
12522 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012523 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012524 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012525 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012526 } else if (app.instrumentationClass != null) {
12527 // Don't want to kill running instrumentation.
12528 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012529 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012530 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012531 } else if (app.curReceiver != null ||
12532 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12533 // An app that is currently receiving a broadcast also
12534 // counts as being in the foreground.
12535 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012536 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012537 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012538 } else if (app.executingServices.size() > 0) {
12539 // An app that is currently executing a service callback also
12540 // counts as being in the foreground.
12541 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012542 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012543 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012544 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012545 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012546 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012547 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012548 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012549 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012550 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012551 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012552 // A very not-needed process. If this is lower in the lru list,
12553 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012554 adj = hiddenAdj;
12555 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012556 app.hidden = true;
12557 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012558 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012559 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012560
12561 // Examine all activities if not already foreground.
12562 if (!app.foregroundActivities && activitiesSize > 0) {
12563 for (int j = 0; j < activitiesSize; j++) {
12564 final ActivityRecord r = app.activities.get(j);
12565 if (r.visible) {
12566 // App has a visible activity; only upgrade adjustment.
12567 if (adj > VISIBLE_APP_ADJ) {
12568 adj = VISIBLE_APP_ADJ;
12569 app.adjType = "visible";
12570 }
12571 schedGroup = Process.THREAD_GROUP_DEFAULT;
12572 app.hidden = false;
12573 app.foregroundActivities = true;
12574 break;
12575 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
12576 || r.state == ActivityState.STOPPING) {
12577 // Only upgrade adjustment.
12578 if (adj > PERCEPTIBLE_APP_ADJ) {
12579 adj = PERCEPTIBLE_APP_ADJ;
12580 app.adjType = "stopping";
12581 }
12582 app.foregroundActivities = true;
12583 }
12584 }
12585 }
12586
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012587 if (adj > PERCEPTIBLE_APP_ADJ) {
12588 if (app.foregroundServices) {
12589 // The user is aware of this app, so make it visible.
12590 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012591 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012592 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012593 } else if (app.forcingToForeground != null) {
12594 // The user is aware of this app, so make it visible.
12595 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012596 app.adjType = "force-foreground";
12597 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012598 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012599 }
12600 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012601
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012602 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12603 // We don't want to kill the current heavy-weight process.
12604 adj = HEAVY_WEIGHT_APP_ADJ;
12605 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12606 app.adjType = "heavy";
12607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012608
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012609 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12610 // This process is hosting what we currently consider to be the
12611 // home app, so we don't want to let it go into the background.
12612 adj = HOME_APP_ADJ;
12613 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12614 app.adjType = "home";
12615 }
12616
Joe Onorato8a9b2202010-02-26 18:56:32 -080012617 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012618
The Android Open Source Project4df24232009-03-05 14:34:35 -080012619 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012620 // there are applications dependent on our services or providers, but
12621 // this gives us a baseline and makes sure we don't get into an
12622 // infinite recursion.
12623 app.adjSeq = mAdjSeq;
12624 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012625
Christopher Tate6fa95972009-06-05 18:43:55 -070012626 if (mBackupTarget != null && app == mBackupTarget.app) {
12627 // If possible we want to avoid killing apps while they're being backed up
12628 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012629 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012630 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012631 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012632 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012633 }
12634 }
12635
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012636 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12637 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012638 final long now = SystemClock.uptimeMillis();
12639 // This process is more important if the top activity is
12640 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012641 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012642 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012643 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012644 if (s.startRequested) {
12645 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12646 // This service has seen some activity within
12647 // recent memory, so we will keep its process ahead
12648 // of the background processes.
12649 if (adj > SECONDARY_SERVER_ADJ) {
12650 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012651 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012652 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012653 }
12654 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012655 // If we have let the service slide into the background
12656 // state, still have some text describing what it is doing
12657 // even though the service no longer has an impact.
12658 if (adj > SECONDARY_SERVER_ADJ) {
12659 app.adjType = "started-bg-services";
12660 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012661 // Don't kill this process because it is doing work; it
12662 // has said it is doing work.
12663 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012664 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012665 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12666 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012667 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012668 = s.connections.values().iterator();
12669 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012670 ArrayList<ConnectionRecord> clist = kt.next();
12671 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12672 // XXX should compute this based on the max of
12673 // all connected clients.
12674 ConnectionRecord cr = clist.get(i);
12675 if (cr.binding.client == app) {
12676 // Binding to ourself is not interesting.
12677 continue;
12678 }
12679 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12680 ProcessRecord client = cr.binding.client;
12681 int myHiddenAdj = hiddenAdj;
12682 if (myHiddenAdj > client.hiddenAdj) {
12683 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12684 myHiddenAdj = client.hiddenAdj;
12685 } else {
12686 myHiddenAdj = VISIBLE_APP_ADJ;
12687 }
12688 }
12689 int clientAdj = computeOomAdjLocked(
12690 client, myHiddenAdj, TOP_APP, true);
12691 if (adj > clientAdj) {
12692 adj = clientAdj >= VISIBLE_APP_ADJ
12693 ? clientAdj : VISIBLE_APP_ADJ;
12694 if (!client.hidden) {
12695 app.hidden = false;
12696 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012697 if (client.keeping) {
12698 app.keeping = true;
12699 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012700 app.adjType = "service";
12701 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12702 .REASON_SERVICE_IN_USE;
12703 app.adjSource = cr.binding.client;
12704 app.adjTarget = s.name;
12705 }
12706 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12707 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12708 schedGroup = Process.THREAD_GROUP_DEFAULT;
12709 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012710 }
12711 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012712 ActivityRecord a = cr.activity;
12713 //if (a != null) {
12714 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12715 //}
12716 if (a != null && adj > FOREGROUND_APP_ADJ &&
12717 (a.state == ActivityState.RESUMED
12718 || a.state == ActivityState.PAUSING)) {
12719 adj = FOREGROUND_APP_ADJ;
12720 schedGroup = Process.THREAD_GROUP_DEFAULT;
12721 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012722 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012723 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12724 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012725 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012726 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012728 }
12729 }
12730 }
12731 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012732
Dianne Hackborn287952c2010-09-22 22:34:31 -070012733 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012734 // would like to avoid killing it unless it would prevent the current
12735 // application from running. By default we put the process in
12736 // with the rest of the background processes; as we scan through
12737 // its services we may bump it up from there.
12738 if (adj > hiddenAdj) {
12739 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012740 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012741 app.adjType = "bg-services";
12742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012743 }
12744
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012745 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12746 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012747 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012748 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12749 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012750 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012751 if (cpr.clients.size() != 0) {
12752 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12753 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12754 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012755 if (client == app) {
12756 // Being our own client is not interesting.
12757 continue;
12758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012759 int myHiddenAdj = hiddenAdj;
12760 if (myHiddenAdj > client.hiddenAdj) {
12761 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12762 myHiddenAdj = client.hiddenAdj;
12763 } else {
12764 myHiddenAdj = FOREGROUND_APP_ADJ;
12765 }
12766 }
12767 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012768 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012769 if (adj > clientAdj) {
12770 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012771 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012772 if (!client.hidden) {
12773 app.hidden = false;
12774 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012775 if (client.keeping) {
12776 app.keeping = true;
12777 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012778 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012779 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12780 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012781 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012782 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012783 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012784 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12785 schedGroup = Process.THREAD_GROUP_DEFAULT;
12786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012787 }
12788 }
12789 // If the provider has external (non-framework) process
12790 // dependencies, ensure that its adjustment is at least
12791 // FOREGROUND_APP_ADJ.
12792 if (cpr.externals != 0) {
12793 if (adj > FOREGROUND_APP_ADJ) {
12794 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012795 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012796 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012797 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012798 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012799 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012800 }
12801 }
12802 }
12803 }
12804
12805 app.curRawAdj = adj;
12806
Joe Onorato8a9b2202010-02-26 18:56:32 -080012807 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012808 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12809 if (adj > app.maxAdj) {
12810 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012811 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012812 schedGroup = Process.THREAD_GROUP_DEFAULT;
12813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012814 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012815 if (adj < HIDDEN_APP_MIN_ADJ) {
12816 app.keeping = true;
12817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012818
12819 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012820 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012821
12822 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkeya4620792011-05-20 15:29:23 -070012823 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED,
12824 app.foregroundActivities ? 1 : 0, 0, app).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012825 }
12826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012827 return adj;
12828 }
12829
12830 /**
12831 * Ask a given process to GC right now.
12832 */
12833 final void performAppGcLocked(ProcessRecord app) {
12834 try {
12835 app.lastRequestedGc = SystemClock.uptimeMillis();
12836 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012837 if (app.reportLowMemory) {
12838 app.reportLowMemory = false;
12839 app.thread.scheduleLowMemory();
12840 } else {
12841 app.thread.processInBackground();
12842 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012843 }
12844 } catch (Exception e) {
12845 // whatever.
12846 }
12847 }
12848
12849 /**
12850 * Returns true if things are idle enough to perform GCs.
12851 */
Josh Bartel7f208742010-02-25 11:01:44 -060012852 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012853 return mParallelBroadcasts.size() == 0
12854 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012855 && (mSleeping || (mMainStack.mResumedActivity != null &&
12856 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012857 }
12858
12859 /**
12860 * Perform GCs on all processes that are waiting for it, but only
12861 * if things are idle.
12862 */
12863 final void performAppGcsLocked() {
12864 final int N = mProcessesToGc.size();
12865 if (N <= 0) {
12866 return;
12867 }
Josh Bartel7f208742010-02-25 11:01:44 -060012868 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012869 while (mProcessesToGc.size() > 0) {
12870 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012871 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012872 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12873 <= SystemClock.uptimeMillis()) {
12874 // To avoid spamming the system, we will GC processes one
12875 // at a time, waiting a few seconds between each.
12876 performAppGcLocked(proc);
12877 scheduleAppGcsLocked();
12878 return;
12879 } else {
12880 // It hasn't been long enough since we last GCed this
12881 // process... put it in the list to wait for its time.
12882 addProcessToGcListLocked(proc);
12883 break;
12884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012885 }
12886 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012887
12888 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012889 }
12890 }
12891
12892 /**
12893 * If all looks good, perform GCs on all processes waiting for them.
12894 */
12895 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012896 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012897 performAppGcsLocked();
12898 return;
12899 }
12900 // Still not idle, wait some more.
12901 scheduleAppGcsLocked();
12902 }
12903
12904 /**
12905 * Schedule the execution of all pending app GCs.
12906 */
12907 final void scheduleAppGcsLocked() {
12908 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012909
12910 if (mProcessesToGc.size() > 0) {
12911 // Schedule a GC for the time to the next process.
12912 ProcessRecord proc = mProcessesToGc.get(0);
12913 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12914
12915 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12916 long now = SystemClock.uptimeMillis();
12917 if (when < (now+GC_TIMEOUT)) {
12918 when = now + GC_TIMEOUT;
12919 }
12920 mHandler.sendMessageAtTime(msg, when);
12921 }
12922 }
12923
12924 /**
12925 * Add a process to the array of processes waiting to be GCed. Keeps the
12926 * list in sorted order by the last GC time. The process can't already be
12927 * on the list.
12928 */
12929 final void addProcessToGcListLocked(ProcessRecord proc) {
12930 boolean added = false;
12931 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12932 if (mProcessesToGc.get(i).lastRequestedGc <
12933 proc.lastRequestedGc) {
12934 added = true;
12935 mProcessesToGc.add(i+1, proc);
12936 break;
12937 }
12938 }
12939 if (!added) {
12940 mProcessesToGc.add(0, proc);
12941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012942 }
12943
12944 /**
12945 * Set up to ask a process to GC itself. This will either do it
12946 * immediately, or put it on the list of processes to gc the next
12947 * time things are idle.
12948 */
12949 final void scheduleAppGcLocked(ProcessRecord app) {
12950 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012951 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012952 return;
12953 }
12954 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012955 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012956 scheduleAppGcsLocked();
12957 }
12958 }
12959
Dianne Hackborn287952c2010-09-22 22:34:31 -070012960 final void checkExcessivePowerUsageLocked(boolean doKills) {
12961 updateCpuStatsNow();
12962
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012963 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012964 boolean doWakeKills = doKills;
12965 boolean doCpuKills = doKills;
12966 if (mLastPowerCheckRealtime == 0) {
12967 doWakeKills = false;
12968 }
12969 if (mLastPowerCheckUptime == 0) {
12970 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012971 }
12972 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012973 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012974 }
12975 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012976 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12977 final long curUptime = SystemClock.uptimeMillis();
12978 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12979 mLastPowerCheckRealtime = curRealtime;
12980 mLastPowerCheckUptime = curUptime;
12981 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12982 doWakeKills = false;
12983 }
12984 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12985 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012986 }
12987 int i = mLruProcesses.size();
12988 while (i > 0) {
12989 i--;
12990 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012991 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012992 long wtime;
12993 synchronized (stats) {
12994 wtime = stats.getProcessWakeTime(app.info.uid,
12995 app.pid, curRealtime);
12996 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012997 long wtimeUsed = wtime - app.lastWakeTime;
12998 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12999 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013000 StringBuilder sb = new StringBuilder(128);
13001 sb.append("Wake for ");
13002 app.toShortString(sb);
13003 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013004 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013005 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013006 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013007 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013008 sb.append((wtimeUsed*100)/realtimeSince);
13009 sb.append("%)");
13010 Slog.i(TAG, sb.toString());
13011 sb.setLength(0);
13012 sb.append("CPU for ");
13013 app.toShortString(sb);
13014 sb.append(": over ");
13015 TimeUtils.formatDuration(uptimeSince, sb);
13016 sb.append(" used ");
13017 TimeUtils.formatDuration(cputimeUsed, sb);
13018 sb.append(" (");
13019 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013020 sb.append("%)");
13021 Slog.i(TAG, sb.toString());
13022 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013023 // If a process has held a wake lock for more
13024 // than 50% of the time during this period,
13025 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070013026 if (doWakeKills && realtimeSince > 0
13027 && ((wtimeUsed*100)/realtimeSince) >= 50) {
13028 synchronized (stats) {
13029 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
13030 realtimeSince, wtimeUsed);
13031 }
13032 Slog.w(TAG, "Excessive wake lock in " + app.processName
13033 + " (pid " + app.pid + "): held " + wtimeUsed
13034 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013035 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13036 app.processName, app.setAdj, "excessive wake lock");
13037 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013038 } else if (doCpuKills && uptimeSince > 0
13039 && ((cputimeUsed*100)/uptimeSince) >= 50) {
13040 synchronized (stats) {
13041 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
13042 uptimeSince, cputimeUsed);
13043 }
13044 Slog.w(TAG, "Excessive CPU in " + app.processName
13045 + " (pid " + app.pid + "): used " + cputimeUsed
13046 + " during " + uptimeSince);
13047 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13048 app.processName, app.setAdj, "excessive cpu");
13049 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013050 } else {
13051 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013052 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013053 }
13054 }
13055 }
13056 }
13057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013058 private final boolean updateOomAdjLocked(
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013059 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013060 app.hiddenAdj = hiddenAdj;
13061
13062 if (app.thread == null) {
13063 return true;
13064 }
13065
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013066 boolean success = true;
13067
Dianne Hackborn287952c2010-09-22 22:34:31 -070013068 final boolean wasKeeping = app.keeping;
13069
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013070 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013071
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013072 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013073 if (app.curRawAdj != app.setRawAdj) {
13074 if (app.curRawAdj > FOREGROUND_APP_ADJ
13075 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13076 // If this app is transitioning from foreground to
13077 // non-foreground, have it do a gc.
13078 scheduleAppGcLocked(app);
13079 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13080 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13081 // Likewise do a gc when an app is moving in to the
13082 // background (such as a service stopping).
13083 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013084 }
13085
13086 if (wasKeeping && !app.keeping) {
13087 // This app is no longer something we want to keep. Note
13088 // its current wake lock time to later know to kill it if
13089 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013090 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
13091 synchronized (stats) {
13092 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
13093 app.pid, SystemClock.elapsedRealtime());
13094 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013095 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013096 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013098 app.setRawAdj = app.curRawAdj;
13099 }
13100 if (adj != app.setAdj) {
13101 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013102 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013103 TAG, "Set app " + app.processName +
13104 " oom adj to " + adj);
13105 app.setAdj = adj;
13106 } else {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013107 success = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013108 }
13109 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013110 if (app.setSchedGroup != app.curSchedGroup) {
13111 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013112 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013113 "Setting process group of " + app.processName
13114 + " to " + app.curSchedGroup);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013115 if (app.waitingToKill != null &&
13116 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
13117 Slog.i(TAG, "Killing " + app + ": " + app.waitingToKill);
13118 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13119 app.processName, app.setAdj, app.waitingToKill);
13120 Process.killProcessQuiet(app.pid);
13121 } else {
13122 if (true) {
13123 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013124 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013125 Process.setProcessGroup(app.pid, app.curSchedGroup);
13126 } catch (Exception e) {
13127 Slog.w(TAG, "Failed setting process group of " + app.pid
13128 + " to " + app.curSchedGroup);
13129 e.printStackTrace();
13130 } finally {
13131 Binder.restoreCallingIdentity(oldId);
13132 }
13133 }
13134 if (false) {
13135 if (app.thread != null) {
13136 try {
13137 app.thread.setSchedulingGroup(app.curSchedGroup);
13138 } catch (RemoteException e) {
13139 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013140 }
13141 }
13142 }
13143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013144 }
13145
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013146 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013147 }
13148
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013149 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013150 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013151 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013152 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013153 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013154 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013155 }
13156 }
13157 return resumedActivity;
13158 }
13159
13160 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013161 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013162 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13163 int curAdj = app.curAdj;
13164 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13165 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13166
13167 mAdjSeq++;
13168
13169 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13170 if (res) {
13171 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13172 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13173 if (nowHidden != wasHidden) {
13174 // Changed to/from hidden state, so apps after it in the LRU
13175 // list may also be changed.
13176 updateOomAdjLocked();
13177 }
13178 }
13179 return res;
13180 }
13181
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013182 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013183 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013184 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013185 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13186
13187 if (false) {
13188 RuntimeException e = new RuntimeException();
13189 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013190 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013191 }
13192
13193 mAdjSeq++;
13194
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013195 // Let's determine how many processes we have running vs.
13196 // how many slots we have for background processes; we may want
13197 // to put multiple processes in a slot of there are enough of
13198 // them.
13199 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13200 int factor = (mLruProcesses.size()-4)/numSlots;
13201 if (factor < 1) factor = 1;
13202 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013203 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013205 // First try updating the OOM adjustment for each of the
13206 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013207 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013208 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
13209 while (i > 0) {
13210 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013211 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013212 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013213 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013214 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013215 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013216 step++;
13217 if (step >= factor) {
13218 step = 0;
13219 curHiddenAdj++;
13220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013221 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013222 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070013223 if (!app.killedBackground) {
13224 numHidden++;
13225 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070013226 Slog.i(TAG, "No longer want " + app.processName
13227 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013228 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13229 app.processName, app.setAdj, "too many background");
13230 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070013231 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013232 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013233 }
13234 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013235 } else {
13236 didOomAdj = false;
13237 }
13238 }
13239
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013240 // If we return false, we will fall back on killing processes to
13241 // have a fixed limit. Do this if a limit has been requested; else
13242 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013243 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13244 }
13245
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013246 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013247 synchronized (this) {
13248 int i;
13249
13250 // First remove any unused application processes whose package
13251 // has been removed.
13252 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13253 final ProcessRecord app = mRemovedProcesses.get(i);
13254 if (app.activities.size() == 0
13255 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013256 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013257 TAG, "Exiting empty application process "
13258 + app.processName + " ("
13259 + (app.thread != null ? app.thread.asBinder() : null)
13260 + ")\n");
13261 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013262 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13263 app.processName, app.setAdj, "empty");
13264 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013265 } else {
13266 try {
13267 app.thread.scheduleExit();
13268 } catch (Exception e) {
13269 // Ignore exceptions.
13270 }
13271 }
13272 cleanUpApplicationRecordLocked(app, false, -1);
13273 mRemovedProcesses.remove(i);
13274
13275 if (app.persistent) {
13276 if (app.persistent) {
13277 addAppLocked(app.info);
13278 }
13279 }
13280 }
13281 }
13282
13283 // Now try updating the OOM adjustment for each of the
13284 // application processes based on their current state.
13285 // If the setOomAdj() API is not supported, then go with our
13286 // back-up plan...
13287 if (!updateOomAdjLocked()) {
13288
13289 // Count how many processes are running services.
13290 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013291 for (i=mLruProcesses.size()-1; i>=0; i--) {
13292 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013293
13294 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013295 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013296 // Don't count processes holding services against our
13297 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013298 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013299 TAG, "Not trimming app " + app + " with services: "
13300 + app.services);
13301 numServiceProcs++;
13302 }
13303 }
13304
13305 int curMaxProcs = mProcessLimit;
13306 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13307 if (mAlwaysFinishActivities) {
13308 curMaxProcs = 1;
13309 }
13310 curMaxProcs += numServiceProcs;
13311
13312 // Quit as many processes as we can to get down to the desired
13313 // process count. First remove any processes that no longer
13314 // have activites running in them.
13315 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013316 i<mLruProcesses.size()
13317 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013318 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013319 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013320 // Quit an application only if it is not currently
13321 // running any activities.
13322 if (!app.persistent && app.activities.size() == 0
13323 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013324 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013325 TAG, "Exiting empty application process "
13326 + app.processName + " ("
13327 + (app.thread != null ? app.thread.asBinder() : null)
13328 + ")\n");
13329 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013330 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13331 app.processName, app.setAdj, "empty");
13332 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013333 } else {
13334 try {
13335 app.thread.scheduleExit();
13336 } catch (Exception e) {
13337 // Ignore exceptions.
13338 }
13339 }
13340 // todo: For now we assume the application is not buggy
13341 // or evil, and will quit as a result of our request.
13342 // Eventually we need to drive this off of the death
13343 // notification, and kill the process if it takes too long.
13344 cleanUpApplicationRecordLocked(app, false, i);
13345 i--;
13346 }
13347 }
13348
13349 // If we still have too many processes, now from the least
13350 // recently used process we start finishing activities.
Joe Onorato43a17652011-04-06 19:22:23 -070013351 if (false) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013352 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013353 " of " + curMaxProcs + " processes");
13354 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013355 i<mLruProcesses.size()
13356 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013357 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013358 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013359 // Quit the application only if we have a state saved for
13360 // all of its activities.
13361 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013362 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013363 int NUMA = app.activities.size();
13364 int j;
Joe Onorato43a17652011-04-06 19:22:23 -070013365 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013366 TAG, "Looking to quit " + app.processName);
13367 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013368 ActivityRecord r = app.activities.get(j);
Joe Onorato43a17652011-04-06 19:22:23 -070013369 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013370 TAG, " " + r.intent.getComponent().flattenToShortString()
13371 + ": frozen=" + r.haveState + ", visible=" + r.visible);
13372 canQuit = (r.haveState || !r.stateNotNeeded)
13373 && !r.visible && r.stopped;
13374 }
13375 if (canQuit) {
13376 // Finish all of the activities, and then the app itself.
13377 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013378 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013379 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013380 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381 }
13382 r.resultTo = null;
13383 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013384 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013385 + app.processName + " ("
13386 + (app.thread != null ? app.thread.asBinder() : null)
13387 + ")\n");
13388 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013389 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13390 app.processName, app.setAdj, "old background");
13391 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013392 } else {
13393 try {
13394 app.thread.scheduleExit();
13395 } catch (Exception e) {
13396 // Ignore exceptions.
13397 }
13398 }
13399 // todo: For now we assume the application is not buggy
13400 // or evil, and will quit as a result of our request.
13401 // Eventually we need to drive this off of the death
13402 // notification, and kill the process if it takes too long.
13403 cleanUpApplicationRecordLocked(app, false, i);
13404 i--;
13405 //dump();
13406 }
13407 }
13408
13409 }
13410
13411 int curMaxActivities = MAX_ACTIVITIES;
13412 if (mAlwaysFinishActivities) {
13413 curMaxActivities = 1;
13414 }
13415
13416 // Finally, if there are too many activities now running, try to
13417 // finish as many as we can to get back down to the limit.
13418 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013419 i<mMainStack.mLRUActivities.size()
13420 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013421 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013422 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013423 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013424
13425 // We can finish this one if we have its icicle saved and
13426 // it is not persistent.
13427 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013428 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013429 final int origSize = mMainStack.mLRUActivities.size();
13430 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013431
13432 // This will remove it from the LRU list, so keep
13433 // our index at the same value. Note that this check to
13434 // see if the size changes is just paranoia -- if
13435 // something unexpected happens, we don't want to end up
13436 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013437 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013438 i--;
13439 }
13440 }
13441 }
13442 }
13443 }
13444
13445 /** This method sends the specified signal to each of the persistent apps */
13446 public void signalPersistentProcesses(int sig) throws RemoteException {
13447 if (sig != Process.SIGNAL_USR1) {
13448 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13449 }
13450
13451 synchronized (this) {
13452 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13453 != PackageManager.PERMISSION_GRANTED) {
13454 throw new SecurityException("Requires permission "
13455 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13456 }
13457
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013458 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13459 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013460 if (r.thread != null && r.persistent) {
13461 Process.sendSignal(r.pid, sig);
13462 }
13463 }
13464 }
13465 }
13466
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013467 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013468 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013469
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013470 try {
13471 synchronized (this) {
13472 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13473 // its own permission.
13474 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13475 != PackageManager.PERMISSION_GRANTED) {
13476 throw new SecurityException("Requires permission "
13477 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013478 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013479
13480 if (start && fd == null) {
13481 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013482 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013483
13484 ProcessRecord proc = null;
13485 try {
13486 int pid = Integer.parseInt(process);
13487 synchronized (mPidsSelfLocked) {
13488 proc = mPidsSelfLocked.get(pid);
13489 }
13490 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013491 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013492
13493 if (proc == null) {
13494 HashMap<String, SparseArray<ProcessRecord>> all
13495 = mProcessNames.getMap();
13496 SparseArray<ProcessRecord> procs = all.get(process);
13497 if (procs != null && procs.size() > 0) {
13498 proc = procs.valueAt(0);
13499 }
13500 }
13501
13502 if (proc == null || proc.thread == null) {
13503 throw new IllegalArgumentException("Unknown process: " + process);
13504 }
13505
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013506 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13507 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013508 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13509 throw new SecurityException("Process not debuggable: " + proc);
13510 }
13511 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013512
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013513 proc.thread.profilerControl(start, path, fd);
13514 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013515 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013516 }
13517 } catch (RemoteException e) {
13518 throw new IllegalStateException("Process disappeared");
13519 } finally {
13520 if (fd != null) {
13521 try {
13522 fd.close();
13523 } catch (IOException e) {
13524 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013525 }
13526 }
13527 }
Andy McFadden824c5102010-07-09 16:26:57 -070013528
13529 public boolean dumpHeap(String process, boolean managed,
13530 String path, ParcelFileDescriptor fd) throws RemoteException {
13531
13532 try {
13533 synchronized (this) {
13534 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13535 // its own permission (same as profileControl).
13536 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13537 != PackageManager.PERMISSION_GRANTED) {
13538 throw new SecurityException("Requires permission "
13539 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13540 }
13541
13542 if (fd == null) {
13543 throw new IllegalArgumentException("null fd");
13544 }
13545
13546 ProcessRecord proc = null;
13547 try {
13548 int pid = Integer.parseInt(process);
13549 synchronized (mPidsSelfLocked) {
13550 proc = mPidsSelfLocked.get(pid);
13551 }
13552 } catch (NumberFormatException e) {
13553 }
13554
13555 if (proc == null) {
13556 HashMap<String, SparseArray<ProcessRecord>> all
13557 = mProcessNames.getMap();
13558 SparseArray<ProcessRecord> procs = all.get(process);
13559 if (procs != null && procs.size() > 0) {
13560 proc = procs.valueAt(0);
13561 }
13562 }
13563
13564 if (proc == null || proc.thread == null) {
13565 throw new IllegalArgumentException("Unknown process: " + process);
13566 }
13567
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013568 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13569 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013570 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13571 throw new SecurityException("Process not debuggable: " + proc);
13572 }
13573 }
13574
13575 proc.thread.dumpHeap(managed, path, fd);
13576 fd = null;
13577 return true;
13578 }
13579 } catch (RemoteException e) {
13580 throw new IllegalStateException("Process disappeared");
13581 } finally {
13582 if (fd != null) {
13583 try {
13584 fd.close();
13585 } catch (IOException e) {
13586 }
13587 }
13588 }
13589 }
13590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013591 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13592 public void monitor() {
13593 synchronized (this) { }
13594 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013595
13596 public void onCoreSettingsChange(Bundle settings) {
13597 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13598 ProcessRecord processRecord = mLruProcesses.get(i);
13599 try {
13600 if (processRecord.thread != null) {
13601 processRecord.thread.setCoreSettings(settings);
13602 }
13603 } catch (RemoteException re) {
13604 /* ignore */
13605 }
13606 }
13607 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070013608
13609 // Multi-user methods
13610
13611 public boolean switchUser(int userid) {
13612 // TODO
13613 return true;
13614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013615}