blob: 2eafc1dc7c24926947dd5d29f6bcd84937dc286b [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;
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080028import com.android.server.wm.WindowManagerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020058import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.Intent;
60import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070061import android.content.IIntentReceiver;
62import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070063import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.pm.ActivityInfo;
65import android.content.pm.ApplicationInfo;
66import android.content.pm.ConfigurationInfo;
67import android.content.pm.IPackageDataObserver;
68import android.content.pm.IPackageManager;
69import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080070import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070072import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.ProviderInfo;
74import android.content.pm.ResolveInfo;
75import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070076import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.content.res.Configuration;
78import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070079import android.net.Proxy;
80import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.net.Uri;
82import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080084import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070085import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080088import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.os.FileUtils;
90import android.os.Handler;
91import android.os.IBinder;
92import android.os.IPermissionController;
93import android.os.Looper;
94import android.os.Message;
95import android.os.Parcel;
96import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070098import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.RemoteException;
100import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700101import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.SystemClock;
103import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.util.Config;
106import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800107import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800108import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.util.PrintWriterPrinter;
110import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700111import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import android.view.Gravity;
113import android.view.LayoutInflater;
114import android.view.View;
115import android.view.WindowManager;
116import android.view.WindowManagerPolicy;
117
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700118import java.io.BufferedInputStream;
119import java.io.BufferedOutputStream;
120import java.io.DataInputStream;
121import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122import java.io.File;
123import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700126import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200127import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800128import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.io.PrintWriter;
130import java.lang.IllegalStateException;
131import java.lang.ref.WeakReference;
132import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700133import java.util.Collections;
134import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135import java.util.HashMap;
136import java.util.HashSet;
137import java.util.Iterator;
138import java.util.List;
139import java.util.Locale;
140import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700141import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700142import java.util.concurrent.atomic.AtomicBoolean;
143import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700145public final class ActivityManagerService extends ActivityManagerNative
146 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 static final String TAG = "ActivityManager";
148 static final boolean DEBUG = false;
149 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
150 static final boolean DEBUG_SWITCH = localLOGV || false;
151 static final boolean DEBUG_TASKS = localLOGV || false;
152 static final boolean DEBUG_PAUSE = localLOGV || false;
153 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
154 static final boolean DEBUG_TRANSITION = localLOGV || false;
155 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700156 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700158 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean DEBUG_VISBILITY = localLOGV || false;
160 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700161 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800162 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700164 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700165 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700166 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700167 static final boolean DEBUG_POWER = localLOGV || false;
168 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 static final boolean VALIDATE_TOKENS = false;
170 static final boolean SHOW_ACTIVITY_START_TIME = true;
171
172 // Control over CPU and battery monitoring.
173 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
174 static final boolean MONITOR_CPU_USAGE = true;
175 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
176 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
177 static final boolean MONITOR_THREAD_CPU_USAGE = false;
178
Dianne Hackborn1655be42009-05-08 14:29:01 -0700179 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700180 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 private static final String SYSTEM_SECURE = "ro.secure";
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800183 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184
185 // This is the maximum number of application processes we would like
186 // to have running. Due to the asynchronous nature of things, we can
187 // temporarily go beyond this limit.
188 static final int MAX_PROCESSES = 2;
189
190 // Set to false to leave processes running indefinitely, relying on
191 // the kernel killing them as resources are required.
192 static final boolean ENFORCE_PROCESS_LIMIT = false;
193
194 // This is the maximum number of activities that we would like to have
195 // running at a given time.
196 static final int MAX_ACTIVITIES = 20;
197
198 // Maximum number of recent tasks that we can remember.
199 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700200
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700201 // Amount of time after a call to stopAppSwitches() during which we will
202 // prevent further untrusted switches from happening.
203 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204
205 // How long we wait for a launched process to attach to the activity manager
206 // before we decide it's never going to come up for real.
207 static final int PROC_START_TIMEOUT = 10*1000;
208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 // How long to wait after going idle before forcing apps to GC.
210 static final int GC_TIMEOUT = 5*1000;
211
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700212 // The minimum amount of time between successive GC requests for a process.
213 static final int GC_MIN_INTERVAL = 60*1000;
214
Dianne Hackborn287952c2010-09-22 22:34:31 -0700215 // The rate at which we check for apps using excessive power -- 15 mins.
216 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
217
218 // The minimum sample duration we will allow before deciding we have
219 // enough data on wake locks to start killing things.
220 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
221
222 // The minimum sample duration we will allow before deciding we have
223 // enough data on CPU usage to start killing things.
224 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 // How long we allow a receiver to run before giving up on it.
227 static final int BROADCAST_TIMEOUT = 10*1000;
228
229 // How long we wait for a service to finish executing.
230 static final int SERVICE_TIMEOUT = 20*1000;
231
232 // How long a service needs to be running until restarting its process
233 // is no longer considered to be a relaunch of the service.
234 static final int SERVICE_RESTART_DURATION = 5*1000;
235
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700236 // How long a service needs to be running until it will start back at
237 // SERVICE_RESTART_DURATION after being killed.
238 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
239
240 // Multiplying factor to increase restart duration time by, for each time
241 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
242 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
243
244 // The minimum amount of time between restarting services that we allow.
245 // That is, when multiple services are restarting, we won't allow each
246 // to restart less than this amount of time from the last one.
247 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 // Maximum amount of time for there to be no activity on a service before
250 // we consider it non-essential and allow its process to go on the
251 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700252 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253
254 // How long we wait until we timeout on key dispatching.
255 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
256
257 // The minimum time we allow between crashes, for us to consider this
258 // application to be bad and stop and its services and reject broadcasts.
259 static final int MIN_CRASH_INTERVAL = 60*1000;
260
261 // How long we wait until we timeout on key dispatching during instrumentation.
262 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
263
264 // OOM adjustments for processes in various states:
265
266 // This is a process without anything currently running in it. Definitely
267 // the first to go! Value set in system/rootdir/init.rc on startup.
268 // This value is initalized in the constructor, careful when refering to
269 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800270 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271
272 // This is a process only hosting activities that are not visible,
273 // so it can be killed without any disruption. Value set in
274 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 static int HIDDEN_APP_MIN_ADJ;
277
The Android Open Source Project4df24232009-03-05 14:34:35 -0800278 // This is a process holding the home application -- we want to try
279 // avoiding killing it, even if it would normally be in the background,
280 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800281 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800282
Christopher Tate6fa95972009-06-05 18:43:55 -0700283 // This is a process currently hosting a backup operation. Killing it
284 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800285 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 // This is a process holding a secondary server -- killing it will not
288 // have much of an impact as far as the user is concerned. Value set in
289 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800290 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700292 // This is a process with a heavy-weight application. It is in the
293 // background, but we want to try to avoid killing it. Value set in
294 // system/rootdir/init.rc on startup.
295 static final int HEAVY_WEIGHT_APP_ADJ;
296
297 // This is a process only hosting components that are perceptible to the
298 // user, and we really want to avoid killing them, but they are not
299 // immediately visible. An example is background music playback. Value set in
300 // system/rootdir/init.rc on startup.
301 static final int PERCEPTIBLE_APP_ADJ;
302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 // This is a process only hosting activities that are visible to the
304 // user, so we'd prefer they don't disappear. Value set in
305 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307
308 // This is the process running the current foreground app. We'd really
309 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800310 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311
312 // This is a process running a core server, such as telephony. Definitely
313 // don't want to kill it, but doing so is not completely fatal.
314 static final int CORE_SERVER_ADJ = -12;
315
316 // The system process runs at the default adjustment.
317 static final int SYSTEM_ADJ = -16;
318
319 // Memory pages are 4K.
320 static final int PAGE_SIZE = 4*1024;
321
322 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800323 static final int EMPTY_APP_MEM;
324 static final int HIDDEN_APP_MEM;
325 static final int HOME_APP_MEM;
326 static final int BACKUP_APP_MEM;
327 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700328 static final int HEAVY_WEIGHT_APP_MEM;
329 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800330 static final int VISIBLE_APP_MEM;
331 static final int FOREGROUND_APP_MEM;
332
333 // The minimum number of hidden apps we want to be able to keep around,
334 // without empty apps being able to push them out of memory.
335 static final int MIN_HIDDEN_APPS = 2;
336
Dianne Hackborn8633e682010-04-22 16:03:41 -0700337 // The maximum number of hidden processes we will keep around before
338 // killing them; this is just a control to not let us go too crazy with
339 // keeping around processes on devices with large amounts of RAM.
340 static final int MAX_HIDDEN_APPS = 15;
341
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800342 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700343 // been idle for less than 15 seconds.
344 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800345
346 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700347 // been idle for less than 120 seconds.
348 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800349
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700350 static int getIntProp(String name, boolean allowZero) {
351 String str = SystemProperties.get(name);
352 if (str == null) {
353 throw new IllegalArgumentException("Property not defined: " + name);
354 }
355 int val = Integer.valueOf(str);
356 if (val == 0 && !allowZero) {
357 throw new IllegalArgumentException("Property must not be zero: " + name);
358 }
359 return val;
360 }
361
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800362 static {
363 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700364 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
365 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
366 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
367 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
368 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
369 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
370 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
371 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
372 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
373 // These days we use the last empty slot for hidden apps as well.
374 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
375 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
376 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
377 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
378 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
379 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
380 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
381 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
382 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
383 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385
Dan Egnor42471dd2010-01-07 17:25:22 -0800386 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387
388 static final String[] EMPTY_STRING_ARRAY = new String[0];
389
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700390 public ActivityStack mMainStack;
391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700393 * Description of a request to start a new activity, which has been held
394 * due to app switches being disabled.
395 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700396 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700397 ActivityRecord r;
398 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700399 Uri[] grantedUriPermissions;
400 int grantedMode;
401 boolean onlyIfNeeded;
402 }
403
404 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
405 = new ArrayList<PendingActivityLaunch>();
406
407 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * List of all active broadcasts that are to be executed immediately
409 * (without waiting for another broadcast to finish). Currently this only
410 * contains broadcasts to registered receivers, to avoid spinning up
411 * a bunch of processes to execute IntentReceiver components.
412 */
413 final ArrayList<BroadcastRecord> mParallelBroadcasts
414 = new ArrayList<BroadcastRecord>();
415
416 /**
417 * List of all active broadcasts that are to be executed one at a time.
418 * The object at the top of the list is the currently activity broadcasts;
419 * those after it are waiting for the top to finish..
420 */
421 final ArrayList<BroadcastRecord> mOrderedBroadcasts
422 = new ArrayList<BroadcastRecord>();
423
424 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800425 * Historical data of past broadcasts, for debugging.
426 */
427 static final int MAX_BROADCAST_HISTORY = 100;
428 final BroadcastRecord[] mBroadcastHistory
429 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
430
431 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 * Set when we current have a BROADCAST_INTENT_MSG in flight.
433 */
434 boolean mBroadcastsScheduled = false;
435
436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * Activity we have told the window manager to have key focus.
438 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700439 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700440 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 * List of intents that were used to start the most recent tasks.
442 */
443 final ArrayList<TaskRecord> mRecentTasks
444 = new ArrayList<TaskRecord>();
445
446 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 * All of the applications we currently have running organized by name.
448 * The keys are strings of the application package name (as
449 * returned by the package manager), and the keys are ApplicationRecord
450 * objects.
451 */
452 final ProcessMap<ProcessRecord> mProcessNames
453 = new ProcessMap<ProcessRecord>();
454
455 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700456 * The currently running heavy-weight process, if any.
457 */
458 ProcessRecord mHeavyWeightProcess = null;
459
460 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 * The last time that various processes have crashed.
462 */
463 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
464
465 /**
466 * Set of applications that we consider to be bad, and will reject
467 * incoming broadcasts from (which the user has no control over).
468 * Processes are added to this set when they have crashed twice within
469 * a minimum amount of time; they are removed from it when they are
470 * later restarted (hopefully due to some user action). The value is the
471 * time it was added to the list.
472 */
473 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
474
475 /**
476 * All of the processes we currently have running organized by pid.
477 * The keys are the pid running the application.
478 *
479 * <p>NOTE: This object is protected by its own lock, NOT the global
480 * activity manager lock!
481 */
482 final SparseArray<ProcessRecord> mPidsSelfLocked
483 = new SparseArray<ProcessRecord>();
484
485 /**
486 * All of the processes that have been forced to be foreground. The key
487 * is the pid of the caller who requested it (we hold a death
488 * link on it).
489 */
490 abstract class ForegroundToken implements IBinder.DeathRecipient {
491 int pid;
492 IBinder token;
493 }
494 final SparseArray<ForegroundToken> mForegroundProcesses
495 = new SparseArray<ForegroundToken>();
496
497 /**
498 * List of records for processes that someone had tried to start before the
499 * system was ready. We don't start them at that point, but ensure they
500 * are started by the time booting is complete.
501 */
502 final ArrayList<ProcessRecord> mProcessesOnHold
503 = new ArrayList<ProcessRecord>();
504
505 /**
506 * List of records for processes that we have started and are waiting
507 * for them to call back. This is really only needed when running in
508 * single processes mode, in which case we do not have a unique pid for
509 * each process.
510 */
511 final ArrayList<ProcessRecord> mStartingProcesses
512 = new ArrayList<ProcessRecord>();
513
514 /**
515 * List of persistent applications that are in the process
516 * of being started.
517 */
518 final ArrayList<ProcessRecord> mPersistentStartingProcesses
519 = new ArrayList<ProcessRecord>();
520
521 /**
522 * Processes that are being forcibly torn down.
523 */
524 final ArrayList<ProcessRecord> mRemovedProcesses
525 = new ArrayList<ProcessRecord>();
526
527 /**
528 * List of running applications, sorted by recent usage.
529 * The first entry in the list is the least recently used.
530 * It contains ApplicationRecord objects. This list does NOT include
531 * any persistent application records (since we never want to exit them).
532 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800533 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 = new ArrayList<ProcessRecord>();
535
536 /**
537 * List of processes that should gc as soon as things are idle.
538 */
539 final ArrayList<ProcessRecord> mProcessesToGc
540 = new ArrayList<ProcessRecord>();
541
542 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800543 * This is the process holding what we currently consider to be
544 * the "home" activity.
545 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700546 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800547
548 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 * Set of PendingResultRecord objects that are currently active.
550 */
551 final HashSet mPendingResultRecords = new HashSet();
552
553 /**
554 * Set of IntentSenderRecord objects that are currently active.
555 */
556 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
557 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
558
559 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800560 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700561 * already logged DropBox entries for. Guarded by itself. If
562 * something (rogue user app) forces this over
563 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
564 */
565 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
566 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
567
568 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700569 * Strict Mode background batched logging state.
570 *
571 * The string buffer is guarded by itself, and its lock is also
572 * used to determine if another batched write is already
573 * in-flight.
574 */
575 private final StringBuilder mStrictModeBuffer = new StringBuilder();
576
577 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700578 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
579 */
580 private boolean mPendingBroadcastTimeoutMessage;
581
582 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 * Intent broadcast that we have tried to start, but are
584 * waiting for its application's process to be created. We only
585 * need one (instead of a list) because we always process broadcasts
586 * one at a time, so no others can be started while waiting for this
587 * one.
588 */
589 BroadcastRecord mPendingBroadcast = null;
590
591 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700592 * The receiver index that is pending, to restart the broadcast if needed.
593 */
594 int mPendingBroadcastRecvIndex;
595
596 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 * Keeps track of all IIntentReceivers that have been registered for
598 * broadcasts. Hash keys are the receiver IBinder, hash value is
599 * a ReceiverList.
600 */
601 final HashMap mRegisteredReceivers = new HashMap();
602
603 /**
604 * Resolver for broadcast intents to registered receivers.
605 * Holds BroadcastFilter (subclass of IntentFilter).
606 */
607 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
608 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
609 @Override
610 protected boolean allowFilterResult(
611 BroadcastFilter filter, List<BroadcastFilter> dest) {
612 IBinder target = filter.receiverList.receiver.asBinder();
613 for (int i=dest.size()-1; i>=0; i--) {
614 if (dest.get(i).receiverList.receiver.asBinder() == target) {
615 return false;
616 }
617 }
618 return true;
619 }
620 };
621
622 /**
623 * State of all active sticky broadcasts. Keys are the action of the
624 * sticky Intent, values are an ArrayList of all broadcasted intents with
625 * that action (which should usually be one).
626 */
627 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
628 new HashMap<String, ArrayList<Intent>>();
629
630 /**
631 * All currently running services.
632 */
633 final HashMap<ComponentName, ServiceRecord> mServices =
634 new HashMap<ComponentName, ServiceRecord>();
635
636 /**
637 * All currently running services indexed by the Intent used to start them.
638 */
639 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
640 new HashMap<Intent.FilterComparison, ServiceRecord>();
641
642 /**
643 * All currently bound service connections. Keys are the IBinder of
644 * the client's IServiceConnection.
645 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700646 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
647 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648
649 /**
650 * List of services that we have been asked to start,
651 * but haven't yet been able to. It is used to hold start requests
652 * while waiting for their corresponding application thread to get
653 * going.
654 */
655 final ArrayList<ServiceRecord> mPendingServices
656 = new ArrayList<ServiceRecord>();
657
658 /**
659 * List of services that are scheduled to restart following a crash.
660 */
661 final ArrayList<ServiceRecord> mRestartingServices
662 = new ArrayList<ServiceRecord>();
663
664 /**
665 * List of services that are in the process of being stopped.
666 */
667 final ArrayList<ServiceRecord> mStoppingServices
668 = new ArrayList<ServiceRecord>();
669
670 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700671 * Backup/restore process management
672 */
673 String mBackupAppName = null;
674 BackupRecord mBackupTarget = null;
675
676 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677 * List of PendingThumbnailsRecord objects of clients who are still
678 * waiting to receive all of the thumbnails for a task.
679 */
680 final ArrayList mPendingThumbnails = new ArrayList();
681
682 /**
683 * List of HistoryRecord objects that have been finished and must
684 * still report back to a pending thumbnail receiver.
685 */
686 final ArrayList mCancelledThumbnails = new ArrayList();
687
688 /**
689 * All of the currently running global content providers. Keys are a
690 * string containing the provider name and values are a
691 * ContentProviderRecord object containing the data about it. Note
692 * that a single provider may be published under multiple names, so
693 * there may be multiple entries here for a single one in mProvidersByClass.
694 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700695 final HashMap<String, ContentProviderRecord> mProvidersByName
696 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697
698 /**
699 * All of the currently running global content providers. Keys are a
700 * string containing the provider's implementation class and values are a
701 * ContentProviderRecord object containing the data about it.
702 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700703 final HashMap<String, ContentProviderRecord> mProvidersByClass
704 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705
706 /**
707 * List of content providers who have clients waiting for them. The
708 * application is currently being launched and the provider will be
709 * removed from this list once it is published.
710 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700711 final ArrayList<ContentProviderRecord> mLaunchingProviders
712 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713
714 /**
715 * Global set of specific Uri permissions that have been granted.
716 */
717 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
718 = new SparseArray<HashMap<Uri, UriPermission>>();
719
720 /**
721 * Thread-local storage used to carry caller permissions over through
722 * indirect content-provider access.
723 * @see #ActivityManagerService.openContentUri()
724 */
725 private class Identity {
726 public int pid;
727 public int uid;
728
729 Identity(int _pid, int _uid) {
730 pid = _pid;
731 uid = _uid;
732 }
733 }
734 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
735
736 /**
737 * All information we have collected about the runtime performance of
738 * any user id that can impact battery performance.
739 */
740 final BatteryStatsService mBatteryStatsService;
741
742 /**
743 * information about component usage
744 */
745 final UsageStatsService mUsageStatsService;
746
747 /**
748 * Current configuration information. HistoryRecord objects are given
749 * a reference to this object to indicate which configuration they are
750 * currently running in, so this object must be kept immutable.
751 */
752 Configuration mConfiguration = new Configuration();
753
754 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800755 * Current sequencing integer of the configuration, for skipping old
756 * configurations.
757 */
758 int mConfigurationSeq = 0;
759
760 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700761 * Hardware-reported OpenGLES version.
762 */
763 final int GL_ES_VERSION;
764
765 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 * List of initialization arguments to pass to all processes when binding applications to them.
767 * For example, references to the commonly used services.
768 */
769 HashMap<String, IBinder> mAppBindArgs;
770
771 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700772 * Temporary to avoid allocations. Protected by main lock.
773 */
774 final StringBuilder mStringBuilder = new StringBuilder(256);
775
776 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 * Used to control how we initialize the service.
778 */
779 boolean mStartRunning = false;
780 ComponentName mTopComponent;
781 String mTopAction;
782 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700783 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 boolean mSystemReady = false;
785 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700786 boolean mWaitingUpdate = false;
787 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700788 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700789 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790
791 Context mContext;
792
793 int mFactoryTest;
794
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700795 boolean mCheckedForSetup;
796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700798 * The time at which we will allow normal application switches again,
799 * after a call to {@link #stopAppSwitches()}.
800 */
801 long mAppSwitchesAllowedTime;
802
803 /**
804 * This is set to true after the first switch after mAppSwitchesAllowedTime
805 * is set; any switches after that will clear the time.
806 */
807 boolean mDidAppSwitch;
808
809 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700810 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700811 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700812 long mLastPowerCheckRealtime;
813
814 /**
815 * Last time (in uptime) at which we checked for power usage.
816 */
817 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700818
819 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 * Set while we are wanting to sleep, to prevent any
821 * activities from being started/resumed.
822 */
823 boolean mSleeping = false;
824
825 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700826 * Set if we are shutting down the system, similar to sleeping.
827 */
828 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829
830 /**
831 * Task identifier that activities are currently being started
832 * in. Incremented each time a new task is created.
833 * todo: Replace this with a TokenSpace class that generates non-repeating
834 * integers that won't wrap.
835 */
836 int mCurTask = 1;
837
838 /**
839 * Current sequence id for oom_adj computation traversal.
840 */
841 int mAdjSeq = 0;
842
843 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700844 * Current sequence id for process LRU updating.
845 */
846 int mLruSeq = 0;
847
848 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
850 * is set, indicating the user wants processes started in such a way
851 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
852 * running in each process (thus no pre-initialized process, etc).
853 */
854 boolean mSimpleProcessManagement = false;
855
856 /**
857 * System monitoring: number of processes that died since the last
858 * N procs were started.
859 */
860 int[] mProcDeaths = new int[20];
861
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700862 /**
863 * This is set if we had to do a delayed dexopt of an app before launching
864 * it, to increasing the ANR timeouts in that case.
865 */
866 boolean mDidDexOpt;
867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 String mDebugApp = null;
869 boolean mWaitForDebugger = false;
870 boolean mDebugTransient = false;
871 String mOrigDebugApp = null;
872 boolean mOrigWaitForDebugger = false;
873 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700874 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700876 final RemoteCallbackList<IActivityWatcher> mWatchers
877 = new RemoteCallbackList<IActivityWatcher>();
878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 /**
880 * Callback of last caller to {@link #requestPss}.
881 */
882 Runnable mRequestPssCallback;
883
884 /**
885 * Remaining processes for which we are waiting results from the last
886 * call to {@link #requestPss}.
887 */
888 final ArrayList<ProcessRecord> mRequestPssList
889 = new ArrayList<ProcessRecord>();
890
891 /**
892 * Runtime statistics collection thread. This object's lock is used to
893 * protect all related state.
894 */
895 final Thread mProcessStatsThread;
896
897 /**
898 * Used to collect process stats when showing not responding dialog.
899 * Protected by mProcessStatsThread.
900 */
901 final ProcessStats mProcessStats = new ProcessStats(
902 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700903 final AtomicLong mLastCpuTime = new AtomicLong(0);
904 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 long mLastWriteTime = 0;
907
908 /**
909 * Set to true after the system has finished booting.
910 */
911 boolean mBooted = false;
912
913 int mProcessLimit = 0;
914
915 WindowManagerService mWindowManager;
916
917 static ActivityManagerService mSelf;
918 static ActivityThread mSystemThread;
919
920 private final class AppDeathRecipient implements IBinder.DeathRecipient {
921 final ProcessRecord mApp;
922 final int mPid;
923 final IApplicationThread mAppThread;
924
925 AppDeathRecipient(ProcessRecord app, int pid,
926 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800927 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 TAG, "New death recipient " + this
929 + " for thread " + thread.asBinder());
930 mApp = app;
931 mPid = pid;
932 mAppThread = thread;
933 }
934
935 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800936 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 TAG, "Death received in " + this
938 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 synchronized(ActivityManagerService.this) {
940 appDiedLocked(mApp, mPid, mAppThread);
941 }
942 }
943 }
944
945 static final int SHOW_ERROR_MSG = 1;
946 static final int SHOW_NOT_RESPONDING_MSG = 2;
947 static final int SHOW_FACTORY_ERROR_MSG = 3;
948 static final int UPDATE_CONFIGURATION_MSG = 4;
949 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
950 static final int WAIT_FOR_DEBUGGER_MSG = 6;
951 static final int BROADCAST_INTENT_MSG = 7;
952 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 static final int SERVICE_TIMEOUT_MSG = 12;
954 static final int UPDATE_TIME_ZONE = 13;
955 static final int SHOW_UID_ERROR_MSG = 14;
956 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700958 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700959 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800960 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700961 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
962 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700963 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700964 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700965 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700966 static final int UPDATE_HTTP_PROXY = 29;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967
968 AlertDialog mUidAlert;
969
970 final Handler mHandler = new Handler() {
971 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800972 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 //}
974
975 public void handleMessage(Message msg) {
976 switch (msg.what) {
977 case SHOW_ERROR_MSG: {
978 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 synchronized (ActivityManagerService.this) {
980 ProcessRecord proc = (ProcessRecord)data.get("app");
981 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800982 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 return;
984 }
985 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700986 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800987 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 d.show();
989 proc.crashDialog = d;
990 } else {
991 // The device is asleep, so just pretend that the user
992 // saw a crash dialog and hit "force quit".
993 res.set(0);
994 }
995 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700996
997 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 } break;
999 case SHOW_NOT_RESPONDING_MSG: {
1000 synchronized (ActivityManagerService.this) {
1001 HashMap data = (HashMap) msg.obj;
1002 ProcessRecord proc = (ProcessRecord)data.get("app");
1003 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001004 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 return;
1006 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001007
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001008 Intent intent = new Intent("android.intent.action.ANR");
1009 if (!mProcessesReady) {
1010 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1011 }
1012 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001013 null, null, 0, null, null, null,
1014 false, false, MY_PID, Process.SYSTEM_UID);
1015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001017 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 d.show();
1019 proc.anrDialog = d;
1020 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001021
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001022 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001024 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1025 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1026 synchronized (ActivityManagerService.this) {
1027 ProcessRecord proc = (ProcessRecord) data.get("app");
1028 if (proc == null) {
1029 Slog.e(TAG, "App not found when showing strict mode dialog.");
1030 break;
1031 }
1032 if (proc.crashDialog != null) {
1033 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1034 return;
1035 }
1036 AppErrorResult res = (AppErrorResult) data.get("result");
1037 if (!mSleeping && !mShuttingDown) {
1038 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1039 d.show();
1040 proc.crashDialog = d;
1041 } else {
1042 // The device is asleep, so just pretend that the user
1043 // saw a crash dialog and hit "force quit".
1044 res.set(0);
1045 }
1046 }
1047 ensureBootCompleted();
1048 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 case SHOW_FACTORY_ERROR_MSG: {
1050 Dialog d = new FactoryErrorDialog(
1051 mContext, msg.getData().getCharSequence("msg"));
1052 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001053 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 } break;
1055 case UPDATE_CONFIGURATION_MSG: {
1056 final ContentResolver resolver = mContext.getContentResolver();
1057 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1058 } break;
1059 case GC_BACKGROUND_PROCESSES_MSG: {
1060 synchronized (ActivityManagerService.this) {
1061 performAppGcsIfAppropriateLocked();
1062 }
1063 } break;
1064 case WAIT_FOR_DEBUGGER_MSG: {
1065 synchronized (ActivityManagerService.this) {
1066 ProcessRecord app = (ProcessRecord)msg.obj;
1067 if (msg.arg1 != 0) {
1068 if (!app.waitedForDebugger) {
1069 Dialog d = new AppWaitingForDebuggerDialog(
1070 ActivityManagerService.this,
1071 mContext, app);
1072 app.waitDialog = d;
1073 app.waitedForDebugger = true;
1074 d.show();
1075 }
1076 } else {
1077 if (app.waitDialog != null) {
1078 app.waitDialog.dismiss();
1079 app.waitDialog = null;
1080 }
1081 }
1082 }
1083 } break;
1084 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001085 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 TAG, "Received BROADCAST_INTENT_MSG");
1087 processNextBroadcast(true);
1088 } break;
1089 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001090 synchronized (ActivityManagerService.this) {
1091 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001095 if (mDidDexOpt) {
1096 mDidDexOpt = false;
1097 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1098 nmsg.obj = msg.obj;
1099 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1100 return;
1101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 serviceTimeout((ProcessRecord)msg.obj);
1103 } break;
1104 case UPDATE_TIME_ZONE: {
1105 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001106 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1107 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 if (r.thread != null) {
1109 try {
1110 r.thread.updateTimeZone();
1111 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001112 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 }
1114 }
1115 }
1116 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001117 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001118 case CLEAR_DNS_CACHE: {
1119 synchronized (ActivityManagerService.this) {
1120 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1121 ProcessRecord r = mLruProcesses.get(i);
1122 if (r.thread != null) {
1123 try {
1124 r.thread.clearDnsCache();
1125 } catch (RemoteException ex) {
1126 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1127 }
1128 }
1129 }
1130 }
1131 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001132 case UPDATE_HTTP_PROXY: {
1133 ProxyProperties proxy = (ProxyProperties)msg.obj;
1134 String host = "";
1135 String port = "";
1136 String exclList = "";
1137 if (proxy != null) {
1138 host = proxy.getHost();
1139 port = Integer.toString(proxy.getPort());
1140 exclList = proxy.getExclusionList();
1141 }
1142 synchronized (ActivityManagerService.this) {
1143 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1144 ProcessRecord r = mLruProcesses.get(i);
1145 if (r.thread != null) {
1146 try {
1147 r.thread.setHttpProxy(host, port, exclList);
1148 } catch (RemoteException ex) {
1149 Slog.w(TAG, "Failed to update http proxy for: " +
1150 r.info.processName);
1151 }
1152 }
1153 }
1154 }
1155 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 case SHOW_UID_ERROR_MSG: {
1157 // XXX This is a temporary dialog, no need to localize.
1158 AlertDialog d = new BaseErrorDialog(mContext);
1159 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1160 d.setCancelable(false);
1161 d.setTitle("System UIDs Inconsistent");
1162 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
Christian Mehlmauer7664e202010-07-20 08:46:17 +02001163 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1165 mUidAlert = d;
1166 d.show();
1167 } break;
1168 case IM_FEELING_LUCKY_MSG: {
1169 if (mUidAlert != null) {
1170 mUidAlert.dismiss();
1171 mUidAlert = null;
1172 }
1173 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001175 if (mDidDexOpt) {
1176 mDidDexOpt = false;
1177 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1178 nmsg.obj = msg.obj;
1179 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1180 return;
1181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 ProcessRecord app = (ProcessRecord)msg.obj;
1183 synchronized (ActivityManagerService.this) {
1184 processStartTimedOutLocked(app);
1185 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001186 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001187 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1188 synchronized (ActivityManagerService.this) {
1189 doPendingActivityLaunchesLocked(true);
1190 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001191 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001192 case KILL_APPLICATION_MSG: {
1193 synchronized (ActivityManagerService.this) {
1194 int uid = msg.arg1;
1195 boolean restart = (msg.arg2 == 1);
1196 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001197 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001198 }
1199 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001200 case FINALIZE_PENDING_INTENT_MSG: {
1201 ((PendingIntentRecord)msg.obj).completeFinalize();
1202 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001203 case POST_HEAVY_NOTIFICATION_MSG: {
1204 INotificationManager inm = NotificationManager.getService();
1205 if (inm == null) {
1206 return;
1207 }
1208
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001209 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001210 ProcessRecord process = root.app;
1211 if (process == null) {
1212 return;
1213 }
1214
1215 try {
1216 Context context = mContext.createPackageContext(process.info.packageName, 0);
1217 String text = mContext.getString(R.string.heavy_weight_notification,
1218 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1219 Notification notification = new Notification();
1220 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1221 notification.when = 0;
1222 notification.flags = Notification.FLAG_ONGOING_EVENT;
1223 notification.tickerText = text;
1224 notification.defaults = 0; // please be quiet
1225 notification.sound = null;
1226 notification.vibrate = null;
1227 notification.setLatestEventInfo(context, text,
1228 mContext.getText(R.string.heavy_weight_notification_detail),
1229 PendingIntent.getActivity(mContext, 0, root.intent,
1230 PendingIntent.FLAG_CANCEL_CURRENT));
1231
1232 try {
1233 int[] outId = new int[1];
1234 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1235 notification, outId);
1236 } catch (RuntimeException e) {
1237 Slog.w(ActivityManagerService.TAG,
1238 "Error showing notification for heavy-weight app", e);
1239 } catch (RemoteException e) {
1240 }
1241 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001242 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001243 }
1244 } break;
1245 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1246 INotificationManager inm = NotificationManager.getService();
1247 if (inm == null) {
1248 return;
1249 }
1250 try {
1251 inm.cancelNotification("android",
1252 R.string.heavy_weight_notification);
1253 } catch (RuntimeException e) {
1254 Slog.w(ActivityManagerService.TAG,
1255 "Error canceling notification for service", e);
1256 } catch (RemoteException e) {
1257 }
1258 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001259 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1260 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001261 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001262 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001263 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1264 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001265 }
1266 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 }
1268 }
1269 };
1270
1271 public static void setSystemProcess() {
1272 try {
1273 ActivityManagerService m = mSelf;
1274
1275 ServiceManager.addService("activity", m);
1276 ServiceManager.addService("meminfo", new MemBinder(m));
1277 if (MONITOR_CPU_USAGE) {
1278 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001280 ServiceManager.addService("permission", new PermissionController(m));
1281
1282 ApplicationInfo info =
1283 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001284 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001285 mSystemThread.installSystemApplicationInfo(info);
1286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 synchronized (mSelf) {
1288 ProcessRecord app = mSelf.newProcessRecordLocked(
1289 mSystemThread.getApplicationThread(), info,
1290 info.processName);
1291 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001292 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293 app.maxAdj = SYSTEM_ADJ;
1294 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1295 synchronized (mSelf.mPidsSelfLocked) {
1296 mSelf.mPidsSelfLocked.put(app.pid, app);
1297 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001298 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 }
1300 } catch (PackageManager.NameNotFoundException e) {
1301 throw new RuntimeException(
1302 "Unable to find android system package", e);
1303 }
1304 }
1305
1306 public void setWindowManager(WindowManagerService wm) {
1307 mWindowManager = wm;
1308 }
1309
1310 public static final Context main(int factoryTest) {
1311 AThread thr = new AThread();
1312 thr.start();
1313
1314 synchronized (thr) {
1315 while (thr.mService == null) {
1316 try {
1317 thr.wait();
1318 } catch (InterruptedException e) {
1319 }
1320 }
1321 }
1322
1323 ActivityManagerService m = thr.mService;
1324 mSelf = m;
1325 ActivityThread at = ActivityThread.systemMain();
1326 mSystemThread = at;
1327 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001328 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 m.mContext = context;
1330 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001331 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332
1333 m.mBatteryStatsService.publish(context);
1334 m.mUsageStatsService.publish(context);
1335
1336 synchronized (thr) {
1337 thr.mReady = true;
1338 thr.notifyAll();
1339 }
1340
1341 m.startRunning(null, null, null, null);
1342
1343 return context;
1344 }
1345
1346 public static ActivityManagerService self() {
1347 return mSelf;
1348 }
1349
1350 static class AThread extends Thread {
1351 ActivityManagerService mService;
1352 boolean mReady = false;
1353
1354 public AThread() {
1355 super("ActivityManager");
1356 }
1357
1358 public void run() {
1359 Looper.prepare();
1360
1361 android.os.Process.setThreadPriority(
1362 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001363 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364
1365 ActivityManagerService m = new ActivityManagerService();
1366
1367 synchronized (this) {
1368 mService = m;
1369 notifyAll();
1370 }
1371
1372 synchronized (this) {
1373 while (!mReady) {
1374 try {
1375 wait();
1376 } catch (InterruptedException e) {
1377 }
1378 }
1379 }
1380
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001381 // For debug builds, log event loop stalls to dropbox for analysis.
1382 if (StrictMode.conditionallyEnableDebugLogging()) {
1383 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1384 }
1385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001386 Looper.loop();
1387 }
1388 }
1389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 static class MemBinder extends Binder {
1391 ActivityManagerService mActivityManagerService;
1392 MemBinder(ActivityManagerService activityManagerService) {
1393 mActivityManagerService = activityManagerService;
1394 }
1395
1396 @Override
1397 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1398 ActivityManagerService service = mActivityManagerService;
1399 ArrayList<ProcessRecord> procs;
1400 synchronized (mActivityManagerService) {
1401 if (args != null && args.length > 0
1402 && args[0].charAt(0) != '-') {
1403 procs = new ArrayList<ProcessRecord>();
1404 int pid = -1;
1405 try {
1406 pid = Integer.parseInt(args[0]);
1407 } catch (NumberFormatException e) {
1408
1409 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001410 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1411 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 if (proc.pid == pid) {
1413 procs.add(proc);
1414 } else if (proc.processName.equals(args[0])) {
1415 procs.add(proc);
1416 }
1417 }
1418 if (procs.size() <= 0) {
1419 pw.println("No process found for: " + args[0]);
1420 return;
1421 }
1422 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001423 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 }
1425 }
1426 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1427 }
1428 }
1429
1430 static class CpuBinder extends Binder {
1431 ActivityManagerService mActivityManagerService;
1432 CpuBinder(ActivityManagerService activityManagerService) {
1433 mActivityManagerService = activityManagerService;
1434 }
1435
1436 @Override
1437 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1438 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001439 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1440 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1441 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 }
1443 }
1444 }
1445
1446 private ActivityManagerService() {
1447 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1448 if (v != null && Integer.getInteger(v) != 0) {
1449 mSimpleProcessManagement = true;
1450 }
1451 v = System.getenv("ANDROID_DEBUG_APP");
1452 if (v != null) {
1453 mSimpleProcessManagement = true;
1454 }
1455
Joe Onorato8a9b2202010-02-26 18:56:32 -08001456 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 File dataDir = Environment.getDataDirectory();
1459 File systemDir = new File(dataDir, "system");
1460 systemDir.mkdirs();
1461 mBatteryStatsService = new BatteryStatsService(new File(
1462 systemDir, "batterystats.bin").toString());
1463 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001464 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001465 mOnBattery = DEBUG_POWER ? true
1466 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001467 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001468
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001469 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001470 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471
Jack Palevichb90d28c2009-07-22 15:35:24 -07001472 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1473 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1474
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001475 mConfiguration.setToDefaults();
1476 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 mProcessStats.init();
1478
1479 // Add ourself to the Watchdog monitors.
1480 Watchdog.getInstance().addMonitor(this);
1481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 mProcessStatsThread = new Thread("ProcessStats") {
1483 public void run() {
1484 while (true) {
1485 try {
1486 try {
1487 synchronized(this) {
1488 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001489 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001491 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 // + ", write delay=" + nextWriteDelay);
1493 if (nextWriteDelay < nextCpuDelay) {
1494 nextCpuDelay = nextWriteDelay;
1495 }
1496 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001497 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 this.wait(nextCpuDelay);
1499 }
1500 }
1501 } catch (InterruptedException e) {
1502 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 updateCpuStatsNow();
1504 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001505 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 }
1507 }
1508 }
1509 };
1510 mProcessStatsThread.start();
1511 }
1512
1513 @Override
1514 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1515 throws RemoteException {
1516 try {
1517 return super.onTransact(code, data, reply, flags);
1518 } catch (RuntimeException e) {
1519 // The activity manager only throws security exceptions, so let's
1520 // log all others.
1521 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001522 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 }
1524 throw e;
1525 }
1526 }
1527
1528 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001529 final long now = SystemClock.uptimeMillis();
1530 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1531 return;
1532 }
1533 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1534 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 mProcessStatsThread.notify();
1536 }
1537 }
1538 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 void updateCpuStatsNow() {
1541 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001542 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 final long now = SystemClock.uptimeMillis();
1544 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001547 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1548 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 haveNewCpuStats = true;
1550 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001551 //Slog.i(TAG, mProcessStats.printCurrentState());
1552 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 // + mProcessStats.getTotalCpuPercent() + "%");
1554
Joe Onorato8a9b2202010-02-26 18:56:32 -08001555 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 if ("true".equals(SystemProperties.get("events.cpu"))) {
1557 int user = mProcessStats.getLastUserTime();
1558 int system = mProcessStats.getLastSystemTime();
1559 int iowait = mProcessStats.getLastIoWaitTime();
1560 int irq = mProcessStats.getLastIrqTime();
1561 int softIrq = mProcessStats.getLastSoftIrqTime();
1562 int idle = mProcessStats.getLastIdleTime();
1563
1564 int total = user + system + iowait + irq + softIrq + idle;
1565 if (total == 0) total = 1;
1566
Doug Zongker2bec3d42009-12-04 12:52:44 -08001567 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 ((user+system+iowait+irq+softIrq) * 100) / total,
1569 (user * 100) / total,
1570 (system * 100) / total,
1571 (iowait * 100) / total,
1572 (irq * 100) / total,
1573 (softIrq * 100) / total);
1574 }
1575 }
1576
Amith Yamasanie43530a2009-08-21 13:11:37 -07001577 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001578 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001579 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 synchronized(mPidsSelfLocked) {
1581 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001582 if (mOnBattery) {
1583 int perc = bstats.startAddingCpuLocked();
1584 int totalUTime = 0;
1585 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001586 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001588 ProcessStats.Stats st = mProcessStats.getStats(i);
1589 if (!st.working) {
1590 continue;
1591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001593 int otherUTime = (st.rel_utime*perc)/100;
1594 int otherSTime = (st.rel_stime*perc)/100;
1595 totalUTime += otherUTime;
1596 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 if (pr != null) {
1598 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001599 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1600 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001601 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001602 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001603 } else {
1604 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001605 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001606 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001607 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1608 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001609 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 }
1612 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001613 bstats.finishAddingCpuLocked(perc, totalUTime,
1614 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 }
1616 }
1617 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1620 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001621 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 }
1623 }
1624 }
1625 }
1626
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001627 @Override
1628 public void batteryNeedsCpuUpdate() {
1629 updateCpuStatsNow();
1630 }
1631
1632 @Override
1633 public void batteryPowerChanged(boolean onBattery) {
1634 // When plugging in, update the CPU stats first before changing
1635 // the plug state.
1636 updateCpuStatsNow();
1637 synchronized (this) {
1638 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001639 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001640 }
1641 }
1642 }
1643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 /**
1645 * Initialize the application bind args. These are passed to each
1646 * process when the bindApplication() IPC is sent to the process. They're
1647 * lazily setup to make sure the services are running when they're asked for.
1648 */
1649 private HashMap<String, IBinder> getCommonServicesLocked() {
1650 if (mAppBindArgs == null) {
1651 mAppBindArgs = new HashMap<String, IBinder>();
1652
1653 // Setup the application init args
1654 mAppBindArgs.put("package", ServiceManager.getService("package"));
1655 mAppBindArgs.put("window", ServiceManager.getService("window"));
1656 mAppBindArgs.put(Context.ALARM_SERVICE,
1657 ServiceManager.getService(Context.ALARM_SERVICE));
1658 }
1659 return mAppBindArgs;
1660 }
1661
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001662 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 if (mFocusedActivity != r) {
1664 mFocusedActivity = r;
1665 mWindowManager.setFocusedApp(r, true);
1666 }
1667 }
1668
Dianne Hackborn906497c2010-05-10 15:57:38 -07001669 private final void updateLruProcessInternalLocked(ProcessRecord app,
1670 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001672 int lrui = mLruProcesses.indexOf(app);
1673 if (lrui >= 0) mLruProcesses.remove(lrui);
1674
1675 int i = mLruProcesses.size()-1;
1676 int skipTop = 0;
1677
Dianne Hackborn906497c2010-05-10 15:57:38 -07001678 app.lruSeq = mLruSeq;
1679
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001680 // compute the new weight for this process.
1681 if (updateActivityTime) {
1682 app.lastActivityTime = SystemClock.uptimeMillis();
1683 }
1684 if (app.activities.size() > 0) {
1685 // If this process has activities, we more strongly want to keep
1686 // it around.
1687 app.lruWeight = app.lastActivityTime;
1688 } else if (app.pubProviders.size() > 0) {
1689 // If this process contains content providers, we want to keep
1690 // it a little more strongly.
1691 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1692 // Also don't let it kick out the first few "real" hidden processes.
1693 skipTop = MIN_HIDDEN_APPS;
1694 } else {
1695 // If this process doesn't have activities, we less strongly
1696 // want to keep it around, and generally want to avoid getting
1697 // in front of any very recently used activities.
1698 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1699 // Also don't let it kick out the first few "real" hidden processes.
1700 skipTop = MIN_HIDDEN_APPS;
1701 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001702
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001703 while (i >= 0) {
1704 ProcessRecord p = mLruProcesses.get(i);
1705 // If this app shouldn't be in front of the first N background
1706 // apps, then skip over that many that are currently hidden.
1707 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1708 skipTop--;
1709 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001710 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001711 mLruProcesses.add(i+1, app);
1712 break;
1713 }
1714 i--;
1715 }
1716 if (i < 0) {
1717 mLruProcesses.add(0, app);
1718 }
1719
Dianne Hackborn906497c2010-05-10 15:57:38 -07001720 // If the app is currently using a content provider or service,
1721 // bump those processes as well.
1722 if (app.connections.size() > 0) {
1723 for (ConnectionRecord cr : app.connections) {
1724 if (cr.binding != null && cr.binding.service != null
1725 && cr.binding.service.app != null
1726 && cr.binding.service.app.lruSeq != mLruSeq) {
1727 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1728 updateActivityTime, i+1);
1729 }
1730 }
1731 }
1732 if (app.conProviders.size() > 0) {
1733 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1734 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1735 updateLruProcessInternalLocked(cpr.app, oomAdj,
1736 updateActivityTime, i+1);
1737 }
1738 }
1739 }
1740
Joe Onorato8a9b2202010-02-26 18:56:32 -08001741 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742 if (oomAdj) {
1743 updateOomAdjLocked();
1744 }
1745 }
1746
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001747 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001748 boolean oomAdj, boolean updateActivityTime) {
1749 mLruSeq++;
1750 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1751 }
1752
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001753 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754 String processName, int uid) {
1755 if (uid == Process.SYSTEM_UID) {
1756 // The system gets to run in any process. If there are multiple
1757 // processes with the same uid, just pick the first (this
1758 // should never happen).
1759 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1760 processName);
1761 return procs != null ? procs.valueAt(0) : null;
1762 }
1763 ProcessRecord proc = mProcessNames.get(processName, uid);
1764 return proc;
1765 }
1766
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001767 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001768 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001769 try {
1770 if (pm.performDexOpt(packageName)) {
1771 mDidDexOpt = true;
1772 }
1773 } catch (RemoteException e) {
1774 }
1775 }
1776
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001777 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001778 int transit = mWindowManager.getPendingAppTransition();
1779 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1780 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1781 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1782 }
1783
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001784 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001786 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1788 // We don't have to do anything more if:
1789 // (1) There is an existing application record; and
1790 // (2) The caller doesn't think it is dead, OR there is no thread
1791 // object attached to it so we know it couldn't have crashed; and
1792 // (3) There is a pid assigned to it, so it is either starting or
1793 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001794 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 + " app=" + app + " knownToBeDead=" + knownToBeDead
1796 + " thread=" + (app != null ? app.thread : null)
1797 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001798 if (app != null && app.pid > 0) {
1799 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001800 // We already have the app running, or are waiting for it to
1801 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001802 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001803 return app;
1804 } else {
1805 // An application record is attached to a previous process,
1806 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001807 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001808 handleAppDiedLocked(app, true);
1809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 String hostingNameStr = hostingName != null
1813 ? hostingName.flattenToShortString() : null;
1814
1815 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1816 // If we are in the background, then check to see if this process
1817 // is bad. If so, we will just silently fail.
1818 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001819 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1820 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001821 return null;
1822 }
1823 } else {
1824 // When the user is explicitly starting a process, then clear its
1825 // crash count so that we won't make it bad until they see at
1826 // least one crash dialog again, and make the process good again
1827 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001828 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1829 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 mProcessCrashTimes.remove(info.processName, info.uid);
1831 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001832 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001833 info.processName);
1834 mBadProcesses.remove(info.processName, info.uid);
1835 if (app != null) {
1836 app.bad = false;
1837 }
1838 }
1839 }
1840
1841 if (app == null) {
1842 app = newProcessRecordLocked(null, info, processName);
1843 mProcessNames.put(processName, info.uid, app);
1844 } else {
1845 // If this is a new package in the process, add the package to the list
1846 app.addPackage(info.packageName);
1847 }
1848
1849 // If the system is not ready yet, then hold off on starting this
1850 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001851 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001852 && !isAllowedWhileBooting(info)
1853 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 if (!mProcessesOnHold.contains(app)) {
1855 mProcessesOnHold.add(app);
1856 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001857 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001858 return app;
1859 }
1860
1861 startProcessLocked(app, hostingType, hostingNameStr);
1862 return (app.pid != 0) ? app : null;
1863 }
1864
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001865 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1866 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1867 }
1868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 private final void startProcessLocked(ProcessRecord app,
1870 String hostingType, String hostingNameStr) {
1871 if (app.pid > 0 && app.pid != MY_PID) {
1872 synchronized (mPidsSelfLocked) {
1873 mPidsSelfLocked.remove(app.pid);
1874 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1875 }
1876 app.pid = 0;
1877 }
1878
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001879 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1880 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881 mProcessesOnHold.remove(app);
1882
1883 updateCpuStats();
1884
1885 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1886 mProcDeaths[0] = 0;
1887
1888 try {
1889 int uid = app.info.uid;
1890 int[] gids = null;
1891 try {
1892 gids = mContext.getPackageManager().getPackageGids(
1893 app.info.packageName);
1894 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001895 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 }
1897 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1898 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1899 && mTopComponent != null
1900 && app.processName.equals(mTopComponent.getPackageName())) {
1901 uid = 0;
1902 }
1903 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1904 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1905 uid = 0;
1906 }
1907 }
1908 int debugFlags = 0;
1909 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1910 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1911 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001912 // Run the app in safe mode if its manifest requests so or the
1913 // system is booted in safe mode.
1914 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1915 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001916 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1917 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001918 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1919 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1920 }
1921 if ("1".equals(SystemProperties.get("debug.assert"))) {
1922 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1923 }
1924 int pid = Process.start("android.app.ActivityThread",
1925 mSimpleProcessManagement ? app.processName : null, uid, uid,
1926 gids, debugFlags, null);
1927 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1928 synchronized (bs) {
1929 if (bs.isOnBattery()) {
1930 app.batteryStats.incStartsLocked();
1931 }
1932 }
1933
Doug Zongker2bec3d42009-12-04 12:52:44 -08001934 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 app.processName, hostingType,
1936 hostingNameStr != null ? hostingNameStr : "");
1937
1938 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001939 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001940 }
1941
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001942 StringBuilder buf = mStringBuilder;
1943 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001944 buf.append("Start proc ");
1945 buf.append(app.processName);
1946 buf.append(" for ");
1947 buf.append(hostingType);
1948 if (hostingNameStr != null) {
1949 buf.append(" ");
1950 buf.append(hostingNameStr);
1951 }
1952 buf.append(": pid=");
1953 buf.append(pid);
1954 buf.append(" uid=");
1955 buf.append(uid);
1956 buf.append(" gids={");
1957 if (gids != null) {
1958 for (int gi=0; gi<gids.length; gi++) {
1959 if (gi != 0) buf.append(", ");
1960 buf.append(gids[gi]);
1961
1962 }
1963 }
1964 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001965 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 if (pid == 0 || pid == MY_PID) {
1967 // Processes are being emulated with threads.
1968 app.pid = MY_PID;
1969 app.removed = false;
1970 mStartingProcesses.add(app);
1971 } else if (pid > 0) {
1972 app.pid = pid;
1973 app.removed = false;
1974 synchronized (mPidsSelfLocked) {
1975 this.mPidsSelfLocked.put(pid, app);
1976 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1977 msg.obj = app;
1978 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1979 }
1980 } else {
1981 app.pid = 0;
1982 RuntimeException e = new RuntimeException(
1983 "Failure starting process " + app.processName
1984 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001985 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001986 }
1987 } catch (RuntimeException e) {
1988 // XXX do better error recovery.
1989 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001990 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001991 }
1992 }
1993
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001994 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001995 if (resumed) {
1996 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1997 } else {
1998 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1999 }
2000 }
2001
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002002 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002003 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2004 && mTopAction == null) {
2005 // We are running in factory test mode, but unable to find
2006 // the factory test app, so just sit around displaying the
2007 // error message and don't try to start anything.
2008 return false;
2009 }
2010 Intent intent = new Intent(
2011 mTopAction,
2012 mTopData != null ? Uri.parse(mTopData) : null);
2013 intent.setComponent(mTopComponent);
2014 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2015 intent.addCategory(Intent.CATEGORY_HOME);
2016 }
2017 ActivityInfo aInfo =
2018 intent.resolveActivityInfo(mContext.getPackageManager(),
2019 STOCK_PM_FLAGS);
2020 if (aInfo != null) {
2021 intent.setComponent(new ComponentName(
2022 aInfo.applicationInfo.packageName, aInfo.name));
2023 // Don't do this if the home app is currently being
2024 // instrumented.
2025 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2026 aInfo.applicationInfo.uid);
2027 if (app == null || app.instrumentationClass == null) {
2028 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002029 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002030 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002031 }
2032 }
2033
2034
2035 return true;
2036 }
2037
2038 /**
2039 * Starts the "new version setup screen" if appropriate.
2040 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002041 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002042 // Only do this once per boot.
2043 if (mCheckedForSetup) {
2044 return;
2045 }
2046
2047 // We will show this screen if the current one is a different
2048 // version than the last one shown, and we are not running in
2049 // low-level factory test mode.
2050 final ContentResolver resolver = mContext.getContentResolver();
2051 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2052 Settings.Secure.getInt(resolver,
2053 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2054 mCheckedForSetup = true;
2055
2056 // See if we should be showing the platform update setup UI.
2057 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2058 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2059 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2060
2061 // We don't allow third party apps to replace this.
2062 ResolveInfo ri = null;
2063 for (int i=0; ris != null && i<ris.size(); i++) {
2064 if ((ris.get(i).activityInfo.applicationInfo.flags
2065 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2066 ri = ris.get(i);
2067 break;
2068 }
2069 }
2070
2071 if (ri != null) {
2072 String vers = ri.activityInfo.metaData != null
2073 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2074 : null;
2075 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2076 vers = ri.activityInfo.applicationInfo.metaData.getString(
2077 Intent.METADATA_SETUP_VERSION);
2078 }
2079 String lastVers = Settings.Secure.getString(
2080 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2081 if (vers != null && !vers.equals(lastVers)) {
2082 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2083 intent.setComponent(new ComponentName(
2084 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002085 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002086 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002087 }
2088 }
2089 }
2090 }
2091
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002092 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002093 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002094
2095 final int identHash = System.identityHashCode(r);
2096 updateUsageStats(r, true);
2097
2098 int i = mWatchers.beginBroadcast();
2099 while (i > 0) {
2100 i--;
2101 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2102 if (w != null) {
2103 try {
2104 w.activityResuming(identHash);
2105 } catch (RemoteException e) {
2106 }
2107 }
2108 }
2109 mWatchers.finishBroadcast();
2110 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002111
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002112 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002113 final int N = mPendingActivityLaunches.size();
2114 if (N <= 0) {
2115 return;
2116 }
2117 for (int i=0; i<N; i++) {
2118 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002119 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002120 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2121 doResume && i == (N-1));
2122 }
2123 mPendingActivityLaunches.clear();
2124 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002125
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002126 public final int startActivity(IApplicationThread caller,
2127 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2128 int grantedMode, IBinder resultTo,
2129 String resultWho, int requestCode, boolean onlyIfNeeded,
2130 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002131 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002132 grantedUriPermissions, grantedMode, resultTo, resultWho,
2133 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002134 }
2135
2136 public final WaitResult startActivityAndWait(IApplicationThread caller,
2137 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2138 int grantedMode, IBinder resultTo,
2139 String resultWho, int requestCode, boolean onlyIfNeeded,
2140 boolean debug) {
2141 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002142 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002143 grantedUriPermissions, grantedMode, resultTo, resultWho,
2144 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002145 return res;
2146 }
2147
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002148 public final int startActivityWithConfig(IApplicationThread caller,
2149 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2150 int grantedMode, IBinder resultTo,
2151 String resultWho, int requestCode, boolean onlyIfNeeded,
2152 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002153 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002154 grantedUriPermissions, grantedMode, resultTo, resultWho,
2155 requestCode, onlyIfNeeded, debug, null, config);
2156 }
2157
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002158 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002159 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002160 IBinder resultTo, String resultWho, int requestCode,
2161 int flagsMask, int flagsValues) {
2162 // Refuse possible leaked file descriptors
2163 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2164 throw new IllegalArgumentException("File descriptors passed in Intent");
2165 }
2166
2167 IIntentSender sender = intent.getTarget();
2168 if (!(sender instanceof PendingIntentRecord)) {
2169 throw new IllegalArgumentException("Bad PendingIntent object");
2170 }
2171
2172 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002173
2174 synchronized (this) {
2175 // If this is coming from the currently resumed activity, it is
2176 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002177 if (mMainStack.mResumedActivity != null
2178 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002179 Binder.getCallingUid()) {
2180 mAppSwitchesAllowedTime = 0;
2181 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002182 }
2183
2184 return pir.sendInner(0, fillInIntent, resolvedType,
2185 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2186 }
2187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 public boolean startNextMatchingActivity(IBinder callingActivity,
2189 Intent intent) {
2190 // Refuse possible leaked file descriptors
2191 if (intent != null && intent.hasFileDescriptors() == true) {
2192 throw new IllegalArgumentException("File descriptors passed in Intent");
2193 }
2194
2195 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002196 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002197 if (index < 0) {
2198 return false;
2199 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002200 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002201 if (r.app == null || r.app.thread == null) {
2202 // The caller is not running... d'oh!
2203 return false;
2204 }
2205 intent = new Intent(intent);
2206 // The caller is not allowed to change the data.
2207 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2208 // And we are resetting to find the next component...
2209 intent.setComponent(null);
2210
2211 ActivityInfo aInfo = null;
2212 try {
2213 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002214 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002216 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002217
2218 // Look for the original activity in the list...
2219 final int N = resolves != null ? resolves.size() : 0;
2220 for (int i=0; i<N; i++) {
2221 ResolveInfo rInfo = resolves.get(i);
2222 if (rInfo.activityInfo.packageName.equals(r.packageName)
2223 && rInfo.activityInfo.name.equals(r.info.name)) {
2224 // We found the current one... the next matching is
2225 // after it.
2226 i++;
2227 if (i<N) {
2228 aInfo = resolves.get(i).activityInfo;
2229 }
2230 break;
2231 }
2232 }
2233 } catch (RemoteException e) {
2234 }
2235
2236 if (aInfo == null) {
2237 // Nobody who is next!
2238 return false;
2239 }
2240
2241 intent.setComponent(new ComponentName(
2242 aInfo.applicationInfo.packageName, aInfo.name));
2243 intent.setFlags(intent.getFlags()&~(
2244 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2245 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2246 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2247 Intent.FLAG_ACTIVITY_NEW_TASK));
2248
2249 // Okay now we need to start the new activity, replacing the
2250 // currently running activity. This is a little tricky because
2251 // we want to start the new one as if the current one is finished,
2252 // but not finish the current one first so that there is no flicker.
2253 // And thus...
2254 final boolean wasFinishing = r.finishing;
2255 r.finishing = true;
2256
2257 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002258 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 final String resultWho = r.resultWho;
2260 final int requestCode = r.requestCode;
2261 r.resultTo = null;
2262 if (resultTo != null) {
2263 resultTo.removeResultsLocked(r, resultWho, requestCode);
2264 }
2265
2266 final long origId = Binder.clearCallingIdentity();
2267 // XXX we are not dealing with propagating grantedUriPermissions...
2268 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002269 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002271 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 Binder.restoreCallingIdentity(origId);
2273
2274 r.finishing = wasFinishing;
2275 if (res != START_SUCCESS) {
2276 return false;
2277 }
2278 return true;
2279 }
2280 }
2281
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002282 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002283 Intent intent, String resolvedType, IBinder resultTo,
2284 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002285
2286 // This is so super not safe, that only the system (or okay root)
2287 // can do it.
2288 final int callingUid = Binder.getCallingUid();
2289 if (callingUid != 0 && callingUid != Process.myUid()) {
2290 throw new SecurityException(
2291 "startActivityInPackage only available to the system");
2292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002294 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2295 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2296 }
2297
2298 public final int startActivities(IApplicationThread caller,
2299 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2300 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2301 }
2302
2303 public final int startActivitiesInPackage(int uid,
2304 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2305
2306 // This is so super not safe, that only the system (or okay root)
2307 // can do it.
2308 final int callingUid = Binder.getCallingUid();
2309 if (callingUid != 0 && callingUid != Process.myUid()) {
2310 throw new SecurityException(
2311 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 }
2313
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002314 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 }
2316
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002317 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002319 // Quick case: check if the top-most recent task is the same.
2320 if (N > 0 && mRecentTasks.get(0) == task) {
2321 return;
2322 }
2323 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 for (int i=0; i<N; i++) {
2325 TaskRecord tr = mRecentTasks.get(i);
2326 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2327 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2328 mRecentTasks.remove(i);
2329 i--;
2330 N--;
2331 if (task.intent == null) {
2332 // If the new recent task we are adding is not fully
2333 // specified, then replace it with the existing recent task.
2334 task = tr;
2335 }
2336 }
2337 }
2338 if (N >= MAX_RECENT_TASKS) {
2339 mRecentTasks.remove(N-1);
2340 }
2341 mRecentTasks.add(0, task);
2342 }
2343
2344 public void setRequestedOrientation(IBinder token,
2345 int requestedOrientation) {
2346 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002347 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002348 if (index < 0) {
2349 return;
2350 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002351 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 final long origId = Binder.clearCallingIdentity();
2353 mWindowManager.setAppOrientation(r, requestedOrientation);
2354 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002355 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002356 r.mayFreezeScreenLocked(r.app) ? r : null);
2357 if (config != null) {
2358 r.frozenBeforeDestroy = true;
2359 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002360 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 }
2362 }
2363 Binder.restoreCallingIdentity(origId);
2364 }
2365 }
2366
2367 public int getRequestedOrientation(IBinder token) {
2368 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002369 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 if (index < 0) {
2371 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2372 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002373 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 return mWindowManager.getAppOrientation(r);
2375 }
2376 }
2377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002378 /**
2379 * This is the internal entry point for handling Activity.finish().
2380 *
2381 * @param token The Binder token referencing the Activity we want to finish.
2382 * @param resultCode Result code, if any, from this Activity.
2383 * @param resultData Result data (Intent), if any, from this Activity.
2384 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002385 * @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 -08002386 */
2387 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2388 // Refuse possible leaked file descriptors
2389 if (resultData != null && resultData.hasFileDescriptors() == true) {
2390 throw new IllegalArgumentException("File descriptors passed in Intent");
2391 }
2392
2393 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002394 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002395 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002396 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397 if (next != null) {
2398 // ask watcher if this is allowed
2399 boolean resumeOK = true;
2400 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002401 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002403 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002404 }
2405
2406 if (!resumeOK) {
2407 return false;
2408 }
2409 }
2410 }
2411 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002412 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002413 resultData, "app-request");
2414 Binder.restoreCallingIdentity(origId);
2415 return res;
2416 }
2417 }
2418
Dianne Hackborn860755f2010-06-03 18:47:52 -07002419 public final void finishHeavyWeightApp() {
2420 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2421 != PackageManager.PERMISSION_GRANTED) {
2422 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2423 + Binder.getCallingPid()
2424 + ", uid=" + Binder.getCallingUid()
2425 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2426 Slog.w(TAG, msg);
2427 throw new SecurityException(msg);
2428 }
2429
2430 synchronized(this) {
2431 if (mHeavyWeightProcess == null) {
2432 return;
2433 }
2434
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002435 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002436 mHeavyWeightProcess.activities);
2437 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002438 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002439 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002440 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002441 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002442 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002443 null, "finish-heavy");
2444 }
2445 }
2446 }
2447
2448 mHeavyWeightProcess = null;
2449 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2450 }
2451 }
2452
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002453 public void crashApplication(int uid, int initialPid, String packageName,
2454 String message) {
2455 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2456 != PackageManager.PERMISSION_GRANTED) {
2457 String msg = "Permission Denial: crashApplication() from pid="
2458 + Binder.getCallingPid()
2459 + ", uid=" + Binder.getCallingUid()
2460 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2461 Slog.w(TAG, msg);
2462 throw new SecurityException(msg);
2463 }
2464
2465 synchronized(this) {
2466 ProcessRecord proc = null;
2467
2468 // Figure out which process to kill. We don't trust that initialPid
2469 // still has any relation to current pids, so must scan through the
2470 // list.
2471 synchronized (mPidsSelfLocked) {
2472 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2473 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2474 if (p.info.uid != uid) {
2475 continue;
2476 }
2477 if (p.pid == initialPid) {
2478 proc = p;
2479 break;
2480 }
2481 for (String str : p.pkgList) {
2482 if (str.equals(packageName)) {
2483 proc = p;
2484 }
2485 }
2486 }
2487 }
2488
2489 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002490 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002491 + " initialPid=" + initialPid
2492 + " packageName=" + packageName);
2493 return;
2494 }
2495
2496 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002497 if (proc.pid == Process.myPid()) {
2498 Log.w(TAG, "crashApplication: trying to crash self!");
2499 return;
2500 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002501 long ident = Binder.clearCallingIdentity();
2502 try {
2503 proc.thread.scheduleCrash(message);
2504 } catch (RemoteException e) {
2505 }
2506 Binder.restoreCallingIdentity(ident);
2507 }
2508 }
2509 }
2510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511 public final void finishSubActivity(IBinder token, String resultWho,
2512 int requestCode) {
2513 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002514 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 if (index < 0) {
2516 return;
2517 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002518 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002519
2520 final long origId = Binder.clearCallingIdentity();
2521
2522 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002523 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2524 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 if (r.resultTo == self && r.requestCode == requestCode) {
2526 if ((r.resultWho == null && resultWho == null) ||
2527 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002528 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002529 Activity.RESULT_CANCELED, null, "request-sub");
2530 }
2531 }
2532 }
2533
2534 Binder.restoreCallingIdentity(origId);
2535 }
2536 }
2537
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002538 public boolean willActivityBeVisible(IBinder token) {
2539 synchronized(this) {
2540 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002541 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2542 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002543 if (r == token) {
2544 return true;
2545 }
2546 if (r.fullscreen && !r.finishing) {
2547 return false;
2548 }
2549 }
2550 return true;
2551 }
2552 }
2553
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002554 public void overridePendingTransition(IBinder token, String packageName,
2555 int enterAnim, int exitAnim) {
2556 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002557 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002558 if (index < 0) {
2559 return;
2560 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002561 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002562
2563 final long origId = Binder.clearCallingIdentity();
2564
2565 if (self.state == ActivityState.RESUMED
2566 || self.state == ActivityState.PAUSING) {
2567 mWindowManager.overridePendingAppTransition(packageName,
2568 enterAnim, exitAnim);
2569 }
2570
2571 Binder.restoreCallingIdentity(origId);
2572 }
2573 }
2574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576 * Main function for removing an existing process from the activity manager
2577 * as a result of that process going away. Clears out all connections
2578 * to the process.
2579 */
2580 private final void handleAppDiedLocked(ProcessRecord app,
2581 boolean restarting) {
2582 cleanUpApplicationRecordLocked(app, restarting, -1);
2583 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002584 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 }
2586
2587 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002588 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2589 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2590 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002592 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2593 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 }
2595
2596 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002597 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002598
2599 boolean atTop = true;
2600 boolean hasVisibleActivities = false;
2601
2602 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002603 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002604 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 TAG, "Removing app " + app + " from history with " + i + " entries");
2606 while (i > 0) {
2607 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002608 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002609 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2611 if (r.app == app) {
2612 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002613 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002614 TAG, "Removing this entry! frozen=" + r.haveState
2615 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002616 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002617 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618
2619 r.inHistory = false;
2620 mWindowManager.removeAppToken(r);
2621 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002622 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002624 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002625
2626 } else {
2627 // We have the current state for this activity, so
2628 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002629 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002630 TAG, "Keeping entry, setting app to null");
2631 if (r.visible) {
2632 hasVisibleActivities = true;
2633 }
2634 r.app = null;
2635 r.nowVisible = false;
2636 if (!r.haveState) {
2637 r.icicle = null;
2638 }
2639 }
2640
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002641 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002642 r.state = ActivityState.STOPPED;
2643 }
2644 atTop = false;
2645 }
2646
2647 app.activities.clear();
2648
2649 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002650 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 + " running instrumentation " + app.instrumentationClass);
2652 Bundle info = new Bundle();
2653 info.putString("shortMsg", "Process crashed.");
2654 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2655 }
2656
2657 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002658 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002659 // If there was nothing to resume, and we are not already
2660 // restarting this process, but there is a visible activity that
2661 // is hosted by the process... then make sure all visible
2662 // activities are running, taking care of restarting this
2663 // process.
2664 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002665 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002666 }
2667 }
2668 }
2669 }
2670
2671 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2672 IBinder threadBinder = thread.asBinder();
2673
2674 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002675 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2676 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002677 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2678 return i;
2679 }
2680 }
2681 return -1;
2682 }
2683
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002684 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002685 IApplicationThread thread) {
2686 if (thread == null) {
2687 return null;
2688 }
2689
2690 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002691 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002692 }
2693
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002694 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002695 IApplicationThread thread) {
2696
2697 mProcDeaths[0]++;
2698
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002699 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2700 synchronized (stats) {
2701 stats.noteProcessDiedLocked(app.info.uid, pid);
2702 }
2703
Magnus Edlund7bb25812010-02-24 15:45:06 +01002704 // Clean up already done if the process has been re-started.
2705 if (app.pid == pid && app.thread != null &&
2706 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002707 if (!app.killedBackground) {
2708 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2709 + ") has died.");
2710 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002711 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002712 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 TAG, "Dying app: " + app + ", pid: " + pid
2714 + ", thread: " + thread.asBinder());
2715 boolean doLowMem = app.instrumentationClass == null;
2716 handleAppDiedLocked(app, false);
2717
2718 if (doLowMem) {
2719 // If there are no longer any background processes running,
2720 // and the app that died was not running instrumentation,
2721 // then tell everyone we are now low on memory.
2722 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002723 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2724 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002725 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2726 haveBg = true;
2727 break;
2728 }
2729 }
2730
2731 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002732 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002733 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002734 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002735 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2736 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002737 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002738 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2739 // The low memory report is overriding any current
2740 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002741 // heavy/important/visible/foreground processes first.
2742 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002743 rec.lastRequestedGc = 0;
2744 } else {
2745 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002746 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002747 rec.reportLowMemory = true;
2748 rec.lastLowMemory = now;
2749 mProcessesToGc.remove(rec);
2750 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002751 }
2752 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002753 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002754 }
2755 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002756 } else if (app.pid != pid) {
2757 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002758 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002759 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002760 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002761 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002762 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763 + thread.asBinder());
2764 }
2765 }
2766
Dan Egnor42471dd2010-01-07 17:25:22 -08002767 /**
2768 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002769 * @param clearTraces causes the dump file to be erased prior to the new
2770 * traces being written, if true; when false, the new traces will be
2771 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002772 * @param firstPids of dalvik VM processes to dump stack traces for first
2773 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002774 * @return file containing stack traces, or null if no dump file is configured
2775 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002776 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2777 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002778 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2779 if (tracesPath == null || tracesPath.length() == 0) {
2780 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002782
2783 File tracesFile = new File(tracesPath);
2784 try {
2785 File tracesDir = tracesFile.getParentFile();
2786 if (!tracesDir.exists()) tracesFile.mkdirs();
2787 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2788
Christopher Tate6ee412d2010-05-28 12:01:56 -07002789 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002790 tracesFile.createNewFile();
2791 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2792 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002793 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002794 return null;
2795 }
2796
2797 // Use a FileObserver to detect when traces finish writing.
2798 // The order of traces is considered important to maintain for legibility.
2799 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2800 public synchronized void onEvent(int event, String path) { notify(); }
2801 };
2802
2803 try {
2804 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002805
2806 // First collect all of the stacks of the most important pids.
2807 try {
2808 int num = firstPids.size();
2809 for (int i = 0; i < num; i++) {
2810 synchronized (observer) {
2811 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2812 observer.wait(200); // Wait for write-close, give up after 200msec
2813 }
2814 }
2815 } catch (InterruptedException e) {
2816 Log.wtf(TAG, e);
2817 }
2818
2819 // Next measure CPU usage.
2820 if (processStats != null) {
2821 processStats.init();
2822 System.gc();
2823 processStats.update();
2824 try {
2825 synchronized (processStats) {
2826 processStats.wait(500); // measure over 1/2 second.
2827 }
2828 } catch (InterruptedException e) {
2829 }
2830 processStats.update();
2831
2832 // We'll take the stack crawls of just the top apps using CPU.
2833 final int N = processStats.countWorkingStats();
2834 int numProcs = 0;
2835 for (int i=0; i<N && numProcs<5; i++) {
2836 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2837 if (lastPids.indexOfKey(stats.pid) >= 0) {
2838 numProcs++;
2839 try {
2840 synchronized (observer) {
2841 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2842 observer.wait(200); // Wait for write-close, give up after 200msec
2843 }
2844 } catch (InterruptedException e) {
2845 Log.wtf(TAG, e);
2846 }
2847
2848 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002849 }
2850 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002851
2852 return tracesFile;
2853
Dan Egnor42471dd2010-01-07 17:25:22 -08002854 } finally {
2855 observer.stopWatching();
2856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002857 }
2858
Jeff Brown4d94a762010-09-23 11:33:28 -07002859 private final class AppNotResponding implements Runnable {
2860 private final ProcessRecord mApp;
2861 private final String mAnnotation;
2862
2863 public AppNotResponding(ProcessRecord app, String annotation) {
2864 mApp = app;
2865 mAnnotation = annotation;
2866 }
2867
2868 @Override
2869 public void run() {
2870 appNotResponding(mApp, null, null, mAnnotation);
2871 }
2872 }
2873
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002874 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2875 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002876 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2877 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2878
Dianne Hackborn287952c2010-09-22 22:34:31 -07002879 if (mController != null) {
2880 try {
2881 // 0 == continue, -1 = kill process immediately
2882 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2883 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2884 } catch (RemoteException e) {
2885 mController = null;
2886 }
2887 }
2888
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002889 long anrTime = SystemClock.uptimeMillis();
2890 if (MONITOR_CPU_USAGE) {
2891 updateCpuStatsNow();
2892 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002893
2894 synchronized (this) {
2895 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2896 if (mShuttingDown) {
2897 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2898 return;
2899 } else if (app.notResponding) {
2900 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2901 return;
2902 } else if (app.crashing) {
2903 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2904 return;
2905 }
2906
2907 // In case we come through here for the same app before completing
2908 // this one, mark as anring now so we will bail out.
2909 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002910
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002911 // Log the ANR to the event log.
2912 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2913 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002914
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002915 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002916 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002917
2918 int parentPid = app.pid;
2919 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002920 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002921
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002922 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002923
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002924 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2925 ProcessRecord r = mLruProcesses.get(i);
2926 if (r != null && r.thread != null) {
2927 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002928 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2929 if (r.persistent) {
2930 firstPids.add(pid);
2931 } else {
2932 lastPids.put(pid, Boolean.TRUE);
2933 }
2934 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002935 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 }
2937 }
2938
Dan Egnor42471dd2010-01-07 17:25:22 -08002939 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002940 StringBuilder info = mStringBuilder;
2941 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002942 info.append("ANR in ").append(app.processName);
2943 if (activity != null && activity.shortComponentName != null) {
2944 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002945 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002946 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002948 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002950 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002951 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002952 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953
Dianne Hackborn287952c2010-09-22 22:34:31 -07002954 final ProcessStats processStats = new ProcessStats(true);
2955
2956 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2957
Dan Egnor42471dd2010-01-07 17:25:22 -08002958 String cpuInfo = null;
2959 if (MONITOR_CPU_USAGE) {
2960 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002961 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002962 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002963 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002964 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002965 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002966 }
2967
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002968 info.append(processStats.printCurrentState(anrTime));
2969
Joe Onorato8a9b2202010-02-26 18:56:32 -08002970 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002971 if (tracesFile == null) {
2972 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2973 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2974 }
2975
2976 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2977
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002978 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002979 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002980 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2981 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002982 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002983 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2984 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 }
2986 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002987 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002988 }
2989 }
2990
Dan Egnor42471dd2010-01-07 17:25:22 -08002991 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2992 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2993 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002994
2995 synchronized (this) {
2996 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2997 Process.killProcess(app.pid);
2998 return;
2999 }
3000
3001 // Set the app's notResponding state, and look up the errorReportReceiver
3002 makeAppNotRespondingLocked(app,
3003 activity != null ? activity.shortComponentName : null,
3004 annotation != null ? "ANR " + annotation : "ANR",
3005 info.toString());
3006
3007 // Bring up the infamous App Not Responding dialog
3008 Message msg = Message.obtain();
3009 HashMap map = new HashMap();
3010 msg.what = SHOW_NOT_RESPONDING_MSG;
3011 msg.obj = map;
3012 map.put("app", app);
3013 if (activity != null) {
3014 map.put("activity", activity);
3015 }
3016
3017 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003018 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 }
3020
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003021 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3022 if (!mLaunchWarningShown) {
3023 mLaunchWarningShown = true;
3024 mHandler.post(new Runnable() {
3025 @Override
3026 public void run() {
3027 synchronized (ActivityManagerService.this) {
3028 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3029 d.show();
3030 mHandler.postDelayed(new Runnable() {
3031 @Override
3032 public void run() {
3033 synchronized (ActivityManagerService.this) {
3034 d.dismiss();
3035 mLaunchWarningShown = false;
3036 }
3037 }
3038 }, 4000);
3039 }
3040 }
3041 });
3042 }
3043 }
3044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 public boolean clearApplicationUserData(final String packageName,
3046 final IPackageDataObserver observer) {
3047 int uid = Binder.getCallingUid();
3048 int pid = Binder.getCallingPid();
3049 long callingId = Binder.clearCallingIdentity();
3050 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003051 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 int pkgUid = -1;
3053 synchronized(this) {
3054 try {
3055 pkgUid = pm.getPackageUid(packageName);
3056 } catch (RemoteException e) {
3057 }
3058 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003059 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003060 return false;
3061 }
3062 if (uid == pkgUid || checkComponentPermission(
3063 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003064 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003066 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003067 } else {
3068 throw new SecurityException(pid+" does not have permission:"+
3069 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3070 "for process:"+packageName);
3071 }
3072 }
3073
3074 try {
3075 //clear application user data
3076 pm.clearApplicationUserData(packageName, observer);
3077 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3078 Uri.fromParts("package", packageName, null));
3079 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003080 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3081 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 } catch (RemoteException e) {
3083 }
3084 } finally {
3085 Binder.restoreCallingIdentity(callingId);
3086 }
3087 return true;
3088 }
3089
Dianne Hackborn03abb812010-01-04 18:43:19 -08003090 public void killBackgroundProcesses(final String packageName) {
3091 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3092 != PackageManager.PERMISSION_GRANTED &&
3093 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3094 != PackageManager.PERMISSION_GRANTED) {
3095 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003096 + Binder.getCallingPid()
3097 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003098 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003099 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 throw new SecurityException(msg);
3101 }
3102
3103 long callingId = Binder.clearCallingIdentity();
3104 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003105 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003106 int pkgUid = -1;
3107 synchronized(this) {
3108 try {
3109 pkgUid = pm.getPackageUid(packageName);
3110 } catch (RemoteException e) {
3111 }
3112 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003113 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003114 return;
3115 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003116 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003117 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003118 }
3119 } finally {
3120 Binder.restoreCallingIdentity(callingId);
3121 }
3122 }
3123
3124 public void forceStopPackage(final String packageName) {
3125 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3126 != PackageManager.PERMISSION_GRANTED) {
3127 String msg = "Permission Denial: forceStopPackage() from pid="
3128 + Binder.getCallingPid()
3129 + ", uid=" + Binder.getCallingUid()
3130 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003131 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003132 throw new SecurityException(msg);
3133 }
3134
3135 long callingId = Binder.clearCallingIdentity();
3136 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003137 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003138 int pkgUid = -1;
3139 synchronized(this) {
3140 try {
3141 pkgUid = pm.getPackageUid(packageName);
3142 } catch (RemoteException e) {
3143 }
3144 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003145 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003146 return;
3147 }
3148 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003149 try {
3150 pm.setPackageStoppedState(packageName, true);
3151 } catch (RemoteException e) {
3152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003153 }
3154 } finally {
3155 Binder.restoreCallingIdentity(callingId);
3156 }
3157 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003158
3159 /*
3160 * The pkg name and uid have to be specified.
3161 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3162 */
3163 public void killApplicationWithUid(String pkg, int uid) {
3164 if (pkg == null) {
3165 return;
3166 }
3167 // Make sure the uid is valid.
3168 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003169 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003170 return;
3171 }
3172 int callerUid = Binder.getCallingUid();
3173 // Only the system server can kill an application
3174 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003175 // Post an aysnc message to kill the application
3176 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3177 msg.arg1 = uid;
3178 msg.arg2 = 0;
3179 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003180 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003181 } else {
3182 throw new SecurityException(callerUid + " cannot kill pkg: " +
3183 pkg);
3184 }
3185 }
3186
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003187 public void closeSystemDialogs(String reason) {
3188 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003189 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003190 if (reason != null) {
3191 intent.putExtra("reason", reason);
3192 }
3193
3194 final int uid = Binder.getCallingUid();
3195 final long origId = Binder.clearCallingIdentity();
3196 synchronized (this) {
3197 int i = mWatchers.beginBroadcast();
3198 while (i > 0) {
3199 i--;
3200 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3201 if (w != null) {
3202 try {
3203 w.closingSystemDialogs(reason);
3204 } catch (RemoteException e) {
3205 }
3206 }
3207 }
3208 mWatchers.finishBroadcast();
3209
Dianne Hackbornffa42482009-09-23 22:20:11 -07003210 mWindowManager.closeSystemDialogs(reason);
3211
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003212 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3213 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003214 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003215 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003216 Activity.RESULT_CANCELED, null, "close-sys");
3217 }
3218 }
3219
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003220 broadcastIntentLocked(null, null, intent, null,
3221 null, 0, null, null, null, false, false, -1, uid);
3222 }
3223 Binder.restoreCallingIdentity(origId);
3224 }
3225
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003226 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003227 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003228 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3229 for (int i=pids.length-1; i>=0; i--) {
3230 infos[i] = new Debug.MemoryInfo();
3231 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003232 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003233 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003234 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003235
3236 public void killApplicationProcess(String processName, int uid) {
3237 if (processName == null) {
3238 return;
3239 }
3240
3241 int callerUid = Binder.getCallingUid();
3242 // Only the system server can kill an application
3243 if (callerUid == Process.SYSTEM_UID) {
3244 synchronized (this) {
3245 ProcessRecord app = getProcessRecordLocked(processName, uid);
3246 if (app != null) {
3247 try {
3248 app.thread.scheduleSuicide();
3249 } catch (RemoteException e) {
3250 // If the other end already died, then our work here is done.
3251 }
3252 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003253 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003254 + processName + " / " + uid);
3255 }
3256 }
3257 } else {
3258 throw new SecurityException(callerUid + " cannot kill app process: " +
3259 processName);
3260 }
3261 }
3262
Dianne Hackborn03abb812010-01-04 18:43:19 -08003263 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003264 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003265 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3266 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003267 if (!mProcessesReady) {
3268 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 intent.putExtra(Intent.EXTRA_UID, uid);
3271 broadcastIntentLocked(null, null, intent,
3272 null, null, 0, null, null, null,
3273 false, false, MY_PID, Process.SYSTEM_UID);
3274 }
3275
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003276 private final boolean killPackageProcessesLocked(String packageName, int uid,
3277 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003278 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003279
Dianne Hackborn03abb812010-01-04 18:43:19 -08003280 // Remove all processes this package may have touched: all with the
3281 // same UID (except for the system or root user), and all whose name
3282 // matches the package name.
3283 final String procNamePrefix = packageName + ":";
3284 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3285 final int NA = apps.size();
3286 for (int ia=0; ia<NA; ia++) {
3287 ProcessRecord app = apps.valueAt(ia);
3288 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003289 if (doit) {
3290 procs.add(app);
3291 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003292 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3293 || app.processName.equals(packageName)
3294 || app.processName.startsWith(procNamePrefix)) {
3295 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003296 if (!doit) {
3297 return true;
3298 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003299 app.removed = true;
3300 procs.add(app);
3301 }
3302 }
3303 }
3304 }
3305
3306 int N = procs.size();
3307 for (int i=0; i<N; i++) {
3308 removeProcessLocked(procs.get(i), callerWillRestart);
3309 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003310 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003311 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003312
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003313 private final boolean forceStopPackageLocked(String name, int uid,
3314 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 int i, N;
3316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 if (uid < 0) {
3318 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003319 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 } catch (RemoteException e) {
3321 }
3322 }
3323
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003324 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003325 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003326
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003327 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3328 while (badApps.hasNext()) {
3329 SparseArray<Long> ba = badApps.next();
3330 if (ba.get(uid) != null) {
3331 badApps.remove();
3332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003333 }
3334 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003335
3336 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3337 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003338
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003339 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3340 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003342 if (!doit) {
3343 return true;
3344 }
3345 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003346 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 if (r.app != null) {
3348 r.app.removed = true;
3349 }
3350 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003351 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003352 }
3353 }
3354
3355 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3356 for (ServiceRecord service : mServices.values()) {
3357 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003358 if (!doit) {
3359 return true;
3360 }
3361 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003362 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 if (service.app != null) {
3364 service.app.removed = true;
3365 }
3366 service.app = null;
3367 services.add(service);
3368 }
3369 }
3370
3371 N = services.size();
3372 for (i=0; i<N; i++) {
3373 bringDownServiceLocked(services.get(i), true);
3374 }
3375
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003376 if (doit) {
3377 if (purgeCache) {
3378 AttributeCache ac = AttributeCache.instance();
3379 if (ac != null) {
3380 ac.removePackage(name);
3381 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003382 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003383 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003384 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003385
3386 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003387 }
3388
3389 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3390 final String name = app.processName;
3391 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003392 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 TAG, "Force removing process " + app + " (" + name
3394 + "/" + uid + ")");
3395
3396 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003397 if (mHeavyWeightProcess == app) {
3398 mHeavyWeightProcess = null;
3399 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 boolean needRestart = false;
3402 if (app.pid > 0 && app.pid != MY_PID) {
3403 int pid = app.pid;
3404 synchronized (mPidsSelfLocked) {
3405 mPidsSelfLocked.remove(pid);
3406 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3407 }
3408 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003409 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 Process.killProcess(pid);
3411
3412 if (app.persistent) {
3413 if (!callerWillRestart) {
3414 addAppLocked(app.info);
3415 } else {
3416 needRestart = true;
3417 }
3418 }
3419 } else {
3420 mRemovedProcesses.add(app);
3421 }
3422
3423 return needRestart;
3424 }
3425
3426 private final void processStartTimedOutLocked(ProcessRecord app) {
3427 final int pid = app.pid;
3428 boolean gone = false;
3429 synchronized (mPidsSelfLocked) {
3430 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3431 if (knownApp != null && knownApp.thread == null) {
3432 mPidsSelfLocked.remove(pid);
3433 gone = true;
3434 }
3435 }
3436
3437 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003438 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003439 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003440 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003442 if (mHeavyWeightProcess == app) {
3443 mHeavyWeightProcess = null;
3444 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3445 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003446 // Take care of any launching providers waiting for this process.
3447 checkAppInLaunchingProvidersLocked(app, true);
3448 // Take care of any services that are waiting for the process.
3449 for (int i=0; i<mPendingServices.size(); i++) {
3450 ServiceRecord sr = mPendingServices.get(i);
3451 if (app.info.uid == sr.appInfo.uid
3452 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003453 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003454 mPendingServices.remove(i);
3455 i--;
3456 bringDownServiceLocked(sr, true);
3457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003458 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003459 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003460 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003461 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003462 try {
3463 IBackupManager bm = IBackupManager.Stub.asInterface(
3464 ServiceManager.getService(Context.BACKUP_SERVICE));
3465 bm.agentDisconnected(app.info.packageName);
3466 } catch (RemoteException e) {
3467 // Can't happen; the backup manager is local
3468 }
3469 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003470 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003471 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003472 mPendingBroadcast.state = BroadcastRecord.IDLE;
3473 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003474 mPendingBroadcast = null;
3475 scheduleBroadcastsLocked();
3476 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003477 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003478 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 }
3480 }
3481
3482 private final boolean attachApplicationLocked(IApplicationThread thread,
3483 int pid) {
3484
3485 // Find the application record that is being attached... either via
3486 // the pid if we are running in multiple processes, or just pull the
3487 // next app record if we are emulating process with anonymous threads.
3488 ProcessRecord app;
3489 if (pid != MY_PID && pid >= 0) {
3490 synchronized (mPidsSelfLocked) {
3491 app = mPidsSelfLocked.get(pid);
3492 }
3493 } else if (mStartingProcesses.size() > 0) {
3494 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003495 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 } else {
3497 app = null;
3498 }
3499
3500 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003501 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003503 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 if (pid > 0 && pid != MY_PID) {
3505 Process.killProcess(pid);
3506 } else {
3507 try {
3508 thread.scheduleExit();
3509 } catch (Exception e) {
3510 // Ignore exceptions.
3511 }
3512 }
3513 return false;
3514 }
3515
3516 // If this application record is still attached to a previous
3517 // process, clean it up now.
3518 if (app.thread != null) {
3519 handleAppDiedLocked(app, true);
3520 }
3521
3522 // Tell the process all about itself.
3523
Joe Onorato8a9b2202010-02-26 18:56:32 -08003524 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003525 TAG, "Binding process pid " + pid + " to record " + app);
3526
3527 String processName = app.processName;
3528 try {
3529 thread.asBinder().linkToDeath(new AppDeathRecipient(
3530 app, pid, thread), 0);
3531 } catch (RemoteException e) {
3532 app.resetPackageList();
3533 startProcessLocked(app, "link fail", processName);
3534 return false;
3535 }
3536
Doug Zongker2bec3d42009-12-04 12:52:44 -08003537 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538
3539 app.thread = thread;
3540 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003541 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3542 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543 app.forcingToForeground = null;
3544 app.foregroundServices = false;
3545 app.debugging = false;
3546
3547 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3548
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003549 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003550 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003552 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003553 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003554 }
3555
Joe Onorato8a9b2202010-02-26 18:56:32 -08003556 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 TAG, "New app record " + app
3558 + " thread=" + thread.asBinder() + " pid=" + pid);
3559 try {
3560 int testMode = IApplicationThread.DEBUG_OFF;
3561 if (mDebugApp != null && mDebugApp.equals(processName)) {
3562 testMode = mWaitForDebugger
3563 ? IApplicationThread.DEBUG_WAIT
3564 : IApplicationThread.DEBUG_ON;
3565 app.debugging = true;
3566 if (mDebugTransient) {
3567 mDebugApp = mOrigDebugApp;
3568 mWaitForDebugger = mOrigWaitForDebugger;
3569 }
3570 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003571
Christopher Tate181fafa2009-05-14 11:12:14 -07003572 // If the app is being launched for restore or full backup, set it up specially
3573 boolean isRestrictedBackupMode = false;
3574 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3575 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3576 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3577 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003578
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003579 ensurePackageDexOpt(app.instrumentationInfo != null
3580 ? app.instrumentationInfo.packageName
3581 : app.info.packageName);
3582 if (app.instrumentationClass != null) {
3583 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003584 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003585 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003586 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003587 thread.bindApplication(processName, app.instrumentationInfo != null
3588 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 app.instrumentationClass, app.instrumentationProfileFile,
3590 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003591 isRestrictedBackupMode || !normalMode,
3592 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003593 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003594 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003595 } catch (Exception e) {
3596 // todo: Yikes! What should we do? For now we will try to
3597 // start another process, but that could easily get us in
3598 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003599 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600
3601 app.resetPackageList();
3602 startProcessLocked(app, "bind fail", processName);
3603 return false;
3604 }
3605
3606 // Remove this record from the list of starting applications.
3607 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003608 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3609 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 mProcessesOnHold.remove(app);
3611
3612 boolean badApp = false;
3613 boolean didSomething = false;
3614
3615 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003616 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003617 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3619 && processName.equals(hr.processName)) {
3620 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003621 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622 didSomething = true;
3623 }
3624 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003625 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 + hr.intent.getComponent().flattenToShortString(), e);
3627 badApp = true;
3628 }
3629 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003630 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003631 }
3632 }
3633
3634 // Find any services that should be running in this process...
3635 if (!badApp && mPendingServices.size() > 0) {
3636 ServiceRecord sr = null;
3637 try {
3638 for (int i=0; i<mPendingServices.size(); i++) {
3639 sr = mPendingServices.get(i);
3640 if (app.info.uid != sr.appInfo.uid
3641 || !processName.equals(sr.processName)) {
3642 continue;
3643 }
3644
3645 mPendingServices.remove(i);
3646 i--;
3647 realStartServiceLocked(sr, app);
3648 didSomething = true;
3649 }
3650 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003651 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003652 + sr.shortName, e);
3653 badApp = true;
3654 }
3655 }
3656
3657 // Check if the next broadcast receiver is in this process...
3658 BroadcastRecord br = mPendingBroadcast;
3659 if (!badApp && br != null && br.curApp == app) {
3660 try {
3661 mPendingBroadcast = null;
3662 processCurBroadcastLocked(br, app);
3663 didSomething = true;
3664 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003665 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003666 + br.curComponent.flattenToShortString(), e);
3667 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003668 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3670 br.resultExtras, br.resultAbort, true);
3671 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003672 // We need to reset the state if we fails to start the receiver.
3673 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 }
3675 }
3676
Christopher Tate181fafa2009-05-14 11:12:14 -07003677 // Check whether the next backup agent is in this process...
3678 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003679 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003680 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003681 try {
3682 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3683 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003684 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003685 e.printStackTrace();
3686 }
3687 }
3688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 if (badApp) {
3690 // todo: Also need to kill application to deal with all
3691 // kinds of exceptions.
3692 handleAppDiedLocked(app, false);
3693 return false;
3694 }
3695
3696 if (!didSomething) {
3697 updateOomAdjLocked();
3698 }
3699
3700 return true;
3701 }
3702
3703 public final void attachApplication(IApplicationThread thread) {
3704 synchronized (this) {
3705 int callingPid = Binder.getCallingPid();
3706 final long origId = Binder.clearCallingIdentity();
3707 attachApplicationLocked(thread, callingPid);
3708 Binder.restoreCallingIdentity(origId);
3709 }
3710 }
3711
Dianne Hackborne88846e2009-09-30 21:34:25 -07003712 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003714 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003715 Binder.restoreCallingIdentity(origId);
3716 }
3717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003719 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003720 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 mWindowManager.enableScreenAfterBoot();
3722 }
3723
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003724 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003725 IntentFilter pkgFilter = new IntentFilter();
3726 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3727 pkgFilter.addDataScheme("package");
3728 mContext.registerReceiver(new BroadcastReceiver() {
3729 @Override
3730 public void onReceive(Context context, Intent intent) {
3731 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3732 if (pkgs != null) {
3733 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003734 synchronized (ActivityManagerService.this) {
3735 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3736 setResultCode(Activity.RESULT_OK);
3737 return;
3738 }
3739 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003740 }
3741 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003742 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003743 }, pkgFilter);
3744
3745 synchronized (this) {
3746 // Ensure that any processes we had put on hold are now started
3747 // up.
3748 final int NP = mProcessesOnHold.size();
3749 if (NP > 0) {
3750 ArrayList<ProcessRecord> procs =
3751 new ArrayList<ProcessRecord>(mProcessesOnHold);
3752 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003753 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3754 + procs.get(ip));
3755 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003756 }
3757 }
3758
3759 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003760 // Start looking for apps that are abusing wake locks.
3761 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003762 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003763 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003764 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003765 broadcastIntentLocked(null, null,
3766 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3767 null, null, 0, null, null,
3768 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3769 false, false, MY_PID, Process.SYSTEM_UID);
3770 }
3771 }
3772 }
3773
3774 final void ensureBootCompleted() {
3775 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003776 boolean enableScreen;
3777 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003778 booting = mBooting;
3779 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003780 enableScreen = !mBooted;
3781 mBooted = true;
3782 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003783
3784 if (booting) {
3785 finishBooting();
3786 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003787
3788 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003789 enableScreenAfterBoot();
3790 }
3791 }
3792
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003793 public final void activityPaused(IBinder token) {
3794 final long origId = Binder.clearCallingIdentity();
3795 mMainStack.activityPaused(token, false);
3796 Binder.restoreCallingIdentity(origId);
3797 }
3798
3799 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3800 CharSequence description) {
3801 if (localLOGV) Slog.v(
3802 TAG, "Activity stopped: token=" + token);
3803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 // Refuse possible leaked file descriptors
3805 if (icicle != null && icicle.hasFileDescriptors()) {
3806 throw new IllegalArgumentException("File descriptors passed in Bundle");
3807 }
3808
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003809 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810
3811 final long origId = Binder.clearCallingIdentity();
3812
3813 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003814 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003815 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003816 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003817 r.icicle = icicle;
3818 r.haveState = true;
3819 if (thumbnail != null) {
3820 r.thumbnail = thumbnail;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003821 if (r.task != null) {
3822 r.task.lastThumbnail = r.thumbnail;
3823 }
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003825 r.description = description;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003826 if (r.task != null) {
3827 r.task.lastDescription = r.description;
3828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003829 r.stopped = true;
3830 r.state = ActivityState.STOPPED;
3831 if (!r.finishing) {
3832 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003833 r.stack.destroyActivityLocked(r, true);
3834 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 }
3836 }
3837 }
3838 }
3839
3840 if (r != null) {
3841 sendPendingThumbnail(r, null, null, null, false);
3842 }
3843
3844 trimApplications();
3845
3846 Binder.restoreCallingIdentity(origId);
3847 }
3848
3849 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003850 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003851 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003852 }
3853
3854 public String getCallingPackage(IBinder token) {
3855 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003856 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003857 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003858 }
3859 }
3860
3861 public ComponentName getCallingActivity(IBinder token) {
3862 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003863 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 return r != null ? r.intent.getComponent() : null;
3865 }
3866 }
3867
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003868 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003869 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003871 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 if (r != null) {
3873 return r.resultTo;
3874 }
3875 }
3876 return null;
3877 }
3878
3879 public ComponentName getActivityClassForToken(IBinder token) {
3880 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003881 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003883 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003884 return r.intent.getComponent();
3885 }
3886 return null;
3887 }
3888 }
3889
3890 public String getPackageForToken(IBinder token) {
3891 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003892 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003894 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003895 return r.packageName;
3896 }
3897 return null;
3898 }
3899 }
3900
3901 public IIntentSender getIntentSender(int type,
3902 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003903 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003904 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003905 if (intents != null) {
3906 if (intents.length < 1) {
3907 throw new IllegalArgumentException("Intents array length must be >= 1");
3908 }
3909 for (int i=0; i<intents.length; i++) {
3910 Intent intent = intents[i];
3911 if (intent == null) {
3912 throw new IllegalArgumentException("Null intent at index " + i);
3913 }
3914 if (intent.hasFileDescriptors()) {
3915 throw new IllegalArgumentException("File descriptors passed in Intent");
3916 }
3917 if (type == INTENT_SENDER_BROADCAST &&
3918 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3919 throw new IllegalArgumentException(
3920 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3921 }
3922 intents[i] = new Intent(intent);
3923 }
3924 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003925 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003926 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003927 }
3928 }
3929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930 synchronized(this) {
3931 int callingUid = Binder.getCallingUid();
3932 try {
3933 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3934 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003935 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003936 .getPackageUid(packageName);
3937 if (uid != Binder.getCallingUid()) {
3938 String msg = "Permission Denial: getIntentSender() from pid="
3939 + Binder.getCallingPid()
3940 + ", uid=" + Binder.getCallingUid()
3941 + ", (need uid=" + uid + ")"
3942 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003943 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944 throw new SecurityException(msg);
3945 }
3946 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003947
3948 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003949 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 } catch (RemoteException e) {
3952 throw new SecurityException(e);
3953 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003954 }
3955 }
3956
3957 IIntentSender getIntentSenderLocked(int type,
3958 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003959 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003960 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003961 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003962 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003963 if (index < 0) {
3964 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003965 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003966 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003967 if (activity.finishing) {
3968 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003969 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003970 }
3971
3972 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3973 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3974 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3975 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3976 |PendingIntent.FLAG_UPDATE_CURRENT);
3977
3978 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3979 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003980 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003981 WeakReference<PendingIntentRecord> ref;
3982 ref = mIntentSenderRecords.get(key);
3983 PendingIntentRecord rec = ref != null ? ref.get() : null;
3984 if (rec != null) {
3985 if (!cancelCurrent) {
3986 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003987 if (rec.key.requestIntent != null) {
3988 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3989 }
3990 if (intents != null) {
3991 intents[intents.length-1] = rec.key.requestIntent;
3992 rec.key.allIntents = intents;
3993 rec.key.allResolvedTypes = resolvedTypes;
3994 } else {
3995 rec.key.allIntents = null;
3996 rec.key.allResolvedTypes = null;
3997 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 return rec;
4000 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004001 rec.canceled = true;
4002 mIntentSenderRecords.remove(key);
4003 }
4004 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004005 return rec;
4006 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004007 rec = new PendingIntentRecord(this, key, callingUid);
4008 mIntentSenderRecords.put(key, rec.ref);
4009 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4010 if (activity.pendingResults == null) {
4011 activity.pendingResults
4012 = new HashSet<WeakReference<PendingIntentRecord>>();
4013 }
4014 activity.pendingResults.add(rec.ref);
4015 }
4016 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004017 }
4018
4019 public void cancelIntentSender(IIntentSender sender) {
4020 if (!(sender instanceof PendingIntentRecord)) {
4021 return;
4022 }
4023 synchronized(this) {
4024 PendingIntentRecord rec = (PendingIntentRecord)sender;
4025 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004026 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004027 .getPackageUid(rec.key.packageName);
4028 if (uid != Binder.getCallingUid()) {
4029 String msg = "Permission Denial: cancelIntentSender() from pid="
4030 + Binder.getCallingPid()
4031 + ", uid=" + Binder.getCallingUid()
4032 + " is not allowed to cancel packges "
4033 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004034 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004035 throw new SecurityException(msg);
4036 }
4037 } catch (RemoteException e) {
4038 throw new SecurityException(e);
4039 }
4040 cancelIntentSenderLocked(rec, true);
4041 }
4042 }
4043
4044 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4045 rec.canceled = true;
4046 mIntentSenderRecords.remove(rec.key);
4047 if (cleanActivity && rec.key.activity != null) {
4048 rec.key.activity.pendingResults.remove(rec.ref);
4049 }
4050 }
4051
4052 public String getPackageForIntentSender(IIntentSender pendingResult) {
4053 if (!(pendingResult instanceof PendingIntentRecord)) {
4054 return null;
4055 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004056 try {
4057 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4058 return res.key.packageName;
4059 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004060 }
4061 return null;
4062 }
4063
4064 public void setProcessLimit(int max) {
4065 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4066 "setProcessLimit()");
4067 mProcessLimit = max;
4068 }
4069
4070 public int getProcessLimit() {
4071 return mProcessLimit;
4072 }
4073
4074 void foregroundTokenDied(ForegroundToken token) {
4075 synchronized (ActivityManagerService.this) {
4076 synchronized (mPidsSelfLocked) {
4077 ForegroundToken cur
4078 = mForegroundProcesses.get(token.pid);
4079 if (cur != token) {
4080 return;
4081 }
4082 mForegroundProcesses.remove(token.pid);
4083 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4084 if (pr == null) {
4085 return;
4086 }
4087 pr.forcingToForeground = null;
4088 pr.foregroundServices = false;
4089 }
4090 updateOomAdjLocked();
4091 }
4092 }
4093
4094 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4095 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4096 "setProcessForeground()");
4097 synchronized(this) {
4098 boolean changed = false;
4099
4100 synchronized (mPidsSelfLocked) {
4101 ProcessRecord pr = mPidsSelfLocked.get(pid);
4102 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004103 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 return;
4105 }
4106 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4107 if (oldToken != null) {
4108 oldToken.token.unlinkToDeath(oldToken, 0);
4109 mForegroundProcesses.remove(pid);
4110 pr.forcingToForeground = null;
4111 changed = true;
4112 }
4113 if (isForeground && token != null) {
4114 ForegroundToken newToken = new ForegroundToken() {
4115 public void binderDied() {
4116 foregroundTokenDied(this);
4117 }
4118 };
4119 newToken.pid = pid;
4120 newToken.token = token;
4121 try {
4122 token.linkToDeath(newToken, 0);
4123 mForegroundProcesses.put(pid, newToken);
4124 pr.forcingToForeground = token;
4125 changed = true;
4126 } catch (RemoteException e) {
4127 // If the process died while doing this, we will later
4128 // do the cleanup with the process death link.
4129 }
4130 }
4131 }
4132
4133 if (changed) {
4134 updateOomAdjLocked();
4135 }
4136 }
4137 }
4138
4139 // =========================================================
4140 // PERMISSIONS
4141 // =========================================================
4142
4143 static class PermissionController extends IPermissionController.Stub {
4144 ActivityManagerService mActivityManagerService;
4145 PermissionController(ActivityManagerService activityManagerService) {
4146 mActivityManagerService = activityManagerService;
4147 }
4148
4149 public boolean checkPermission(String permission, int pid, int uid) {
4150 return mActivityManagerService.checkPermission(permission, pid,
4151 uid) == PackageManager.PERMISSION_GRANTED;
4152 }
4153 }
4154
4155 /**
4156 * This can be called with or without the global lock held.
4157 */
4158 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004159 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004160 // We might be performing an operation on behalf of an indirect binder
4161 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4162 // client identity accordingly before proceeding.
4163 Identity tlsIdentity = sCallerIdentity.get();
4164 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004165 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4167 uid = tlsIdentity.uid;
4168 pid = tlsIdentity.pid;
4169 }
4170
4171 // Root, system server and our own process get to do everything.
4172 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4173 !Process.supportsProcesses()) {
4174 return PackageManager.PERMISSION_GRANTED;
4175 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004176 // If there is a uid that owns whatever is being accessed, it has
4177 // blanket access to it regardless of the permissions it requires.
4178 if (owningUid >= 0 && uid == owningUid) {
4179 return PackageManager.PERMISSION_GRANTED;
4180 }
4181 // If the target is not exported, then nobody else can get to it.
4182 if (!exported) {
4183 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004184 return PackageManager.PERMISSION_DENIED;
4185 }
4186 if (permission == null) {
4187 return PackageManager.PERMISSION_GRANTED;
4188 }
4189 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004190 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004191 .checkUidPermission(permission, uid);
4192 } catch (RemoteException e) {
4193 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004194 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004195 }
4196 return PackageManager.PERMISSION_DENIED;
4197 }
4198
4199 /**
4200 * As the only public entry point for permissions checking, this method
4201 * can enforce the semantic that requesting a check on a null global
4202 * permission is automatically denied. (Internally a null permission
4203 * string is used when calling {@link #checkComponentPermission} in cases
4204 * when only uid-based security is needed.)
4205 *
4206 * This can be called with or without the global lock held.
4207 */
4208 public int checkPermission(String permission, int pid, int uid) {
4209 if (permission == null) {
4210 return PackageManager.PERMISSION_DENIED;
4211 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004212 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004213 }
4214
4215 /**
4216 * Binder IPC calls go through the public entry point.
4217 * This can be called with or without the global lock held.
4218 */
4219 int checkCallingPermission(String permission) {
4220 return checkPermission(permission,
4221 Binder.getCallingPid(),
4222 Binder.getCallingUid());
4223 }
4224
4225 /**
4226 * This can be called with or without the global lock held.
4227 */
4228 void enforceCallingPermission(String permission, String func) {
4229 if (checkCallingPermission(permission)
4230 == PackageManager.PERMISSION_GRANTED) {
4231 return;
4232 }
4233
4234 String msg = "Permission Denial: " + func + " from pid="
4235 + Binder.getCallingPid()
4236 + ", uid=" + Binder.getCallingUid()
4237 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004238 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004239 throw new SecurityException(msg);
4240 }
4241
4242 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004243 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4244 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4245 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4246 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4247 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004248 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004249 // Is the component private from the target uid?
4250 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4251
4252 // Acceptable if the there is no read permission needed from the
4253 // target or the target is holding the read permission.
4254 if (!readPerm) {
4255 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004256 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004257 == PackageManager.PERMISSION_GRANTED)) {
4258 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 }
4260 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004261
4262 // Acceptable if the there is no write permission needed from the
4263 // target or the target is holding the read permission.
4264 if (!writePerm) {
4265 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004266 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004267 == PackageManager.PERMISSION_GRANTED)) {
4268 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 }
4270 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004271
4272 // Acceptable if there is a path permission matching the URI that
4273 // the target holds the permission on.
4274 PathPermission[] pps = pi.pathPermissions;
4275 if (pps != null && (!readPerm || !writePerm)) {
4276 final String path = uri.getPath();
4277 int i = pps.length;
4278 while (i > 0 && (!readPerm || !writePerm)) {
4279 i--;
4280 PathPermission pp = pps[i];
4281 if (!readPerm) {
4282 final String pprperm = pp.getReadPermission();
4283 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4284 + pprperm + " for " + pp.getPath()
4285 + ": match=" + pp.match(path)
4286 + " check=" + pm.checkUidPermission(pprperm, uid));
4287 if (pprperm != null && pp.match(path) &&
4288 (pm.checkUidPermission(pprperm, uid)
4289 == PackageManager.PERMISSION_GRANTED)) {
4290 readPerm = true;
4291 }
4292 }
4293 if (!writePerm) {
4294 final String ppwperm = pp.getWritePermission();
4295 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4296 + ppwperm + " for " + pp.getPath()
4297 + ": match=" + pp.match(path)
4298 + " check=" + pm.checkUidPermission(ppwperm, uid));
4299 if (ppwperm != null && pp.match(path) &&
4300 (pm.checkUidPermission(ppwperm, uid)
4301 == PackageManager.PERMISSION_GRANTED)) {
4302 writePerm = true;
4303 }
4304 }
4305 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004306 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 } catch (RemoteException e) {
4308 return false;
4309 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004310
4311 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004312 }
4313
4314 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4315 int modeFlags) {
4316 // Root gets to do everything.
4317 if (uid == 0 || !Process.supportsProcesses()) {
4318 return true;
4319 }
4320 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4321 if (perms == null) return false;
4322 UriPermission perm = perms.get(uri);
4323 if (perm == null) return false;
4324 return (modeFlags&perm.modeFlags) == modeFlags;
4325 }
4326
4327 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4328 // Another redirected-binder-call permissions check as in
4329 // {@link checkComponentPermission}.
4330 Identity tlsIdentity = sCallerIdentity.get();
4331 if (tlsIdentity != null) {
4332 uid = tlsIdentity.uid;
4333 pid = tlsIdentity.pid;
4334 }
4335
4336 // Our own process gets to do everything.
4337 if (pid == MY_PID) {
4338 return PackageManager.PERMISSION_GRANTED;
4339 }
4340 synchronized(this) {
4341 return checkUriPermissionLocked(uri, uid, modeFlags)
4342 ? PackageManager.PERMISSION_GRANTED
4343 : PackageManager.PERMISSION_DENIED;
4344 }
4345 }
4346
Dianne Hackborn39792d22010-08-19 18:01:52 -07004347 /**
4348 * Check if the targetPkg can be granted permission to access uri by
4349 * the callingUid using the given modeFlags. Throws a security exception
4350 * if callingUid is not allowed to do this. Returns the uid of the target
4351 * if the URI permission grant should be performed; returns -1 if it is not
4352 * needed (for example targetPkg already has permission to access the URI).
4353 */
4354 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4355 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004356 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4357 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4358 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004359 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 }
4361
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004362 if (targetPkg != null) {
4363 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4364 "Checking grant " + targetPkg + " permission to " + uri);
4365 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004366
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004367 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368
4369 // If this is not a content: uri, we can't do anything with it.
4370 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004371 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004372 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004373 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 }
4375
4376 String name = uri.getAuthority();
4377 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004378 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004379 if (cpr != null) {
4380 pi = cpr.info;
4381 } else {
4382 try {
4383 pi = pm.resolveContentProvider(name,
4384 PackageManager.GET_URI_PERMISSION_PATTERNS);
4385 } catch (RemoteException ex) {
4386 }
4387 }
4388 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004389 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004390 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 }
4392
4393 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004394 if (targetPkg != null) {
4395 try {
4396 targetUid = pm.getPackageUid(targetPkg);
4397 if (targetUid < 0) {
4398 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4399 "Can't grant URI permission no uid for: " + targetPkg);
4400 return -1;
4401 }
4402 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004403 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004404 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004405 } else {
4406 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004407 }
4408
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004409 if (targetUid >= 0) {
4410 // First... does the target actually need this permission?
4411 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4412 // No need to grant the target this permission.
4413 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4414 "Target " + targetPkg + " already has full permission to " + uri);
4415 return -1;
4416 }
4417 } else {
4418 // First... there is no target package, so can anyone access it?
4419 boolean allowed = pi.exported;
4420 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4421 if (pi.readPermission != null) {
4422 allowed = false;
4423 }
4424 }
4425 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4426 if (pi.writePermission != null) {
4427 allowed = false;
4428 }
4429 }
4430 if (allowed) {
4431 return -1;
4432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004433 }
4434
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004435 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 if (!pi.grantUriPermissions) {
4437 throw new SecurityException("Provider " + pi.packageName
4438 + "/" + pi.name
4439 + " does not allow granting of Uri permissions (uri "
4440 + uri + ")");
4441 }
4442 if (pi.uriPermissionPatterns != null) {
4443 final int N = pi.uriPermissionPatterns.length;
4444 boolean allowed = false;
4445 for (int i=0; i<N; i++) {
4446 if (pi.uriPermissionPatterns[i] != null
4447 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4448 allowed = true;
4449 break;
4450 }
4451 }
4452 if (!allowed) {
4453 throw new SecurityException("Provider " + pi.packageName
4454 + "/" + pi.name
4455 + " does not allow granting of permission to path of Uri "
4456 + uri);
4457 }
4458 }
4459
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004460 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004462 if (callingUid != Process.myUid()) {
4463 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4464 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4465 throw new SecurityException("Uid " + callingUid
4466 + " does not have permission to uri " + uri);
4467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004468 }
4469 }
4470
Dianne Hackborn39792d22010-08-19 18:01:52 -07004471 return targetUid;
4472 }
4473
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004474 public int checkGrantUriPermission(int callingUid, String targetPkg,
4475 Uri uri, int modeFlags) {
4476 synchronized(this) {
4477 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4478 }
4479 }
4480
Dianne Hackborn39792d22010-08-19 18:01:52 -07004481 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4482 Uri uri, int modeFlags, UriPermissionOwner owner) {
4483 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4484 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4485 if (modeFlags == 0) {
4486 return;
4487 }
4488
4489 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 // to the uri, and the target doesn't. Let's now give this to
4491 // the target.
4492
Joe Onorato8a9b2202010-02-26 18:56:32 -08004493 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004494 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 HashMap<Uri, UriPermission> targetUris
4497 = mGrantedUriPermissions.get(targetUid);
4498 if (targetUris == null) {
4499 targetUris = new HashMap<Uri, UriPermission>();
4500 mGrantedUriPermissions.put(targetUid, targetUris);
4501 }
4502
4503 UriPermission perm = targetUris.get(uri);
4504 if (perm == null) {
4505 perm = new UriPermission(targetUid, uri);
4506 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004507 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004509 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004510 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004511 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004512 } else {
4513 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4514 perm.readOwners.add(owner);
4515 owner.addReadPermission(perm);
4516 }
4517 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4518 perm.writeOwners.add(owner);
4519 owner.addWritePermission(perm);
4520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 }
4522 }
4523
Dianne Hackborn39792d22010-08-19 18:01:52 -07004524 void grantUriPermissionLocked(int callingUid,
4525 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004526 if (targetPkg == null) {
4527 throw new NullPointerException("targetPkg");
4528 }
4529
Dianne Hackborn39792d22010-08-19 18:01:52 -07004530 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4531 if (targetUid < 0) {
4532 return;
4533 }
4534
4535 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4536 }
4537
4538 /**
4539 * Like checkGrantUriPermissionLocked, but takes an Intent.
4540 */
4541 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4542 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004543 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004544 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004545 + " from " + intent + "; flags=0x"
4546 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4547
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004548 if (targetPkg == null) {
4549 throw new NullPointerException("targetPkg");
4550 }
4551
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004552 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004553 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 }
4555 Uri data = intent.getData();
4556 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004557 return -1;
4558 }
4559 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4560 intent.getFlags());
4561 }
4562
4563 /**
4564 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4565 */
4566 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4567 String targetPkg, Intent intent, UriPermissionOwner owner) {
4568 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4569 intent.getFlags(), owner);
4570 }
4571
4572 void grantUriPermissionFromIntentLocked(int callingUid,
4573 String targetPkg, Intent intent, UriPermissionOwner owner) {
4574 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4575 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 return;
4577 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004578
4579 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004580 }
4581
4582 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4583 Uri uri, int modeFlags) {
4584 synchronized(this) {
4585 final ProcessRecord r = getRecordForAppLocked(caller);
4586 if (r == null) {
4587 throw new SecurityException("Unable to find app for caller "
4588 + caller
4589 + " when granting permission to uri " + uri);
4590 }
4591 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004592 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 }
4594 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004595 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004596 }
4597
4598 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4599 null);
4600 }
4601 }
4602
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004603 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004604 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4605 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4606 HashMap<Uri, UriPermission> perms
4607 = mGrantedUriPermissions.get(perm.uid);
4608 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004609 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004610 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004611 perms.remove(perm.uri);
4612 if (perms.size() == 0) {
4613 mGrantedUriPermissions.remove(perm.uid);
4614 }
4615 }
4616 }
4617 }
4618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4620 int modeFlags) {
4621 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4622 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4623 if (modeFlags == 0) {
4624 return;
4625 }
4626
Joe Onorato8a9b2202010-02-26 18:56:32 -08004627 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004628 "Revoking all granted permissions to " + uri);
4629
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004630 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004631
4632 final String authority = uri.getAuthority();
4633 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004634 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635 if (cpr != null) {
4636 pi = cpr.info;
4637 } else {
4638 try {
4639 pi = pm.resolveContentProvider(authority,
4640 PackageManager.GET_URI_PERMISSION_PATTERNS);
4641 } catch (RemoteException ex) {
4642 }
4643 }
4644 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004645 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004646 return;
4647 }
4648
4649 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004650 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004651 // Right now, if you are not the original owner of the permission,
4652 // you are not allowed to revoke it.
4653 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4654 throw new SecurityException("Uid " + callingUid
4655 + " does not have permission to uri " + uri);
4656 //}
4657 }
4658
4659 // Go through all of the permissions and remove any that match.
4660 final List<String> SEGMENTS = uri.getPathSegments();
4661 if (SEGMENTS != null) {
4662 final int NS = SEGMENTS.size();
4663 int N = mGrantedUriPermissions.size();
4664 for (int i=0; i<N; i++) {
4665 HashMap<Uri, UriPermission> perms
4666 = mGrantedUriPermissions.valueAt(i);
4667 Iterator<UriPermission> it = perms.values().iterator();
4668 toploop:
4669 while (it.hasNext()) {
4670 UriPermission perm = it.next();
4671 Uri targetUri = perm.uri;
4672 if (!authority.equals(targetUri.getAuthority())) {
4673 continue;
4674 }
4675 List<String> targetSegments = targetUri.getPathSegments();
4676 if (targetSegments == null) {
4677 continue;
4678 }
4679 if (targetSegments.size() < NS) {
4680 continue;
4681 }
4682 for (int j=0; j<NS; j++) {
4683 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4684 continue toploop;
4685 }
4686 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004687 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004688 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004689 perm.clearModes(modeFlags);
4690 if (perm.modeFlags == 0) {
4691 it.remove();
4692 }
4693 }
4694 if (perms.size() == 0) {
4695 mGrantedUriPermissions.remove(
4696 mGrantedUriPermissions.keyAt(i));
4697 N--;
4698 i--;
4699 }
4700 }
4701 }
4702 }
4703
4704 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4705 int modeFlags) {
4706 synchronized(this) {
4707 final ProcessRecord r = getRecordForAppLocked(caller);
4708 if (r == null) {
4709 throw new SecurityException("Unable to find app for caller "
4710 + caller
4711 + " when revoking permission to uri " + uri);
4712 }
4713 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004714 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004715 return;
4716 }
4717
4718 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4719 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4720 if (modeFlags == 0) {
4721 return;
4722 }
4723
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004724 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004725
4726 final String authority = uri.getAuthority();
4727 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004728 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004729 if (cpr != null) {
4730 pi = cpr.info;
4731 } else {
4732 try {
4733 pi = pm.resolveContentProvider(authority,
4734 PackageManager.GET_URI_PERMISSION_PATTERNS);
4735 } catch (RemoteException ex) {
4736 }
4737 }
4738 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004739 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 return;
4741 }
4742
4743 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4744 }
4745 }
4746
Dianne Hackborn7e269642010-08-25 19:50:20 -07004747 @Override
4748 public IBinder newUriPermissionOwner(String name) {
4749 synchronized(this) {
4750 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4751 return owner.getExternalTokenLocked();
4752 }
4753 }
4754
4755 @Override
4756 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4757 Uri uri, int modeFlags) {
4758 synchronized(this) {
4759 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4760 if (owner == null) {
4761 throw new IllegalArgumentException("Unknown owner: " + token);
4762 }
4763 if (fromUid != Binder.getCallingUid()) {
4764 if (Binder.getCallingUid() != Process.myUid()) {
4765 // Only system code can grant URI permissions on behalf
4766 // of other users.
4767 throw new SecurityException("nice try");
4768 }
4769 }
4770 if (targetPkg == null) {
4771 throw new IllegalArgumentException("null target");
4772 }
4773 if (uri == null) {
4774 throw new IllegalArgumentException("null uri");
4775 }
4776
4777 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4778 }
4779 }
4780
4781 @Override
4782 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4783 synchronized(this) {
4784 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4785 if (owner == null) {
4786 throw new IllegalArgumentException("Unknown owner: " + token);
4787 }
4788
4789 if (uri == null) {
4790 owner.removeUriPermissionsLocked(mode);
4791 } else {
4792 owner.removeUriPermissionLocked(uri, mode);
4793 }
4794 }
4795 }
4796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4798 synchronized (this) {
4799 ProcessRecord app =
4800 who != null ? getRecordForAppLocked(who) : null;
4801 if (app == null) return;
4802
4803 Message msg = Message.obtain();
4804 msg.what = WAIT_FOR_DEBUGGER_MSG;
4805 msg.obj = app;
4806 msg.arg1 = waiting ? 1 : 0;
4807 mHandler.sendMessage(msg);
4808 }
4809 }
4810
4811 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4812 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004813 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004814 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004815 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816 }
4817
4818 // =========================================================
4819 // TASK MANAGEMENT
4820 // =========================================================
4821
4822 public List getTasks(int maxNum, int flags,
4823 IThumbnailReceiver receiver) {
4824 ArrayList list = new ArrayList();
4825
4826 PendingThumbnailsRecord pending = null;
4827 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004828 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004829
4830 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004831 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4833 + ", receiver=" + receiver);
4834
4835 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4836 != PackageManager.PERMISSION_GRANTED) {
4837 if (receiver != null) {
4838 // If the caller wants to wait for pending thumbnails,
4839 // it ain't gonna get them.
4840 try {
4841 receiver.finished();
4842 } catch (RemoteException ex) {
4843 }
4844 }
4845 String msg = "Permission Denial: getTasks() from pid="
4846 + Binder.getCallingPid()
4847 + ", uid=" + Binder.getCallingUid()
4848 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004849 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004850 throw new SecurityException(msg);
4851 }
4852
Dianne Hackbornd2835932010-12-13 16:28:46 -08004853 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4854 && checkCallingPermission(
4855 android.Manifest.permission.READ_FRAME_BUFFER)
4856 == PackageManager.PERMISSION_GRANTED;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004857
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004858 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004859 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004860 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004861 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004862 CharSequence topDescription = null;
4863 TaskRecord curTask = null;
4864 int numActivities = 0;
4865 int numRunning = 0;
4866 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004867 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004869 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004870
4871 // Initialize state for next task if needed.
4872 if (top == null ||
4873 (top.state == ActivityState.INITIALIZING
4874 && top.task == r.task)) {
4875 top = r;
4876 topDescription = r.description;
4877 curTask = r.task;
4878 numActivities = numRunning = 0;
4879 }
4880
4881 // Add 'r' into the current task.
4882 numActivities++;
4883 if (r.app != null && r.app.thread != null) {
4884 numRunning++;
4885 }
4886 if (topDescription == null) {
4887 topDescription = r.description;
4888 }
4889
Joe Onorato8a9b2202010-02-26 18:56:32 -08004890 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 TAG, r.intent.getComponent().flattenToShortString()
4892 + ": task=" + r.task);
4893
4894 // If the next one is a different task, generate a new
4895 // TaskInfo entry for what we have.
4896 if (next == null || next.task != curTask) {
4897 ActivityManager.RunningTaskInfo ci
4898 = new ActivityManager.RunningTaskInfo();
4899 ci.id = curTask.taskId;
4900 ci.baseActivity = r.intent.getComponent();
4901 ci.topActivity = top.intent.getComponent();
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004902 if (canReadFb) {
4903 if (top.thumbnail != null) {
4904 ci.thumbnail = top.thumbnail;
4905 } else if (top.state == ActivityState.RESUMED) {
Dianne Hackbornd2835932010-12-13 16:28:46 -08004906 ci.thumbnail = top.stack.screenshotActivities(top);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004907 }
4908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004909 ci.description = topDescription;
4910 ci.numActivities = numActivities;
4911 ci.numRunning = numRunning;
4912 //System.out.println(
4913 // "#" + maxNum + ": " + " descr=" + ci.description);
4914 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004915 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004916 TAG, "State=" + top.state + "Idle=" + top.idle
4917 + " app=" + top.app
4918 + " thr=" + (top.app != null ? top.app.thread : null));
4919 if (top.state == ActivityState.RESUMED
4920 || top.state == ActivityState.PAUSING) {
4921 if (top.idle && top.app != null
4922 && top.app.thread != null) {
4923 topRecord = top;
4924 topThumbnail = top.app.thread;
4925 } else {
4926 top.thumbnailNeeded = true;
4927 }
4928 }
4929 if (pending == null) {
4930 pending = new PendingThumbnailsRecord(receiver);
4931 }
4932 pending.pendingRecords.add(top);
4933 }
4934 list.add(ci);
4935 maxNum--;
4936 top = null;
4937 }
4938 }
4939
4940 if (pending != null) {
4941 mPendingThumbnails.add(pending);
4942 }
4943 }
4944
Joe Onorato8a9b2202010-02-26 18:56:32 -08004945 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004946
4947 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004948 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949 try {
4950 topThumbnail.requestThumbnail(topRecord);
4951 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004952 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004953 sendPendingThumbnail(null, topRecord, null, null, true);
4954 }
4955 }
4956
4957 if (pending == null && receiver != null) {
4958 // In this case all thumbnails were available and the client
4959 // is being asked to be told when the remaining ones come in...
4960 // which is unusually, since the top-most currently running
4961 // activity should never have a canned thumbnail! Oh well.
4962 try {
4963 receiver.finished();
4964 } catch (RemoteException ex) {
4965 }
4966 }
4967
4968 return list;
4969 }
4970
4971 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4972 int flags) {
4973 synchronized (this) {
4974 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4975 "getRecentTasks()");
4976
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004977 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004978
Dianne Hackbornd2835932010-12-13 16:28:46 -08004979 ActivityRecord resumed = mMainStack.mResumedActivity;
4980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004981 final int N = mRecentTasks.size();
4982 ArrayList<ActivityManager.RecentTaskInfo> res
4983 = new ArrayList<ActivityManager.RecentTaskInfo>(
4984 maxNum < N ? maxNum : N);
4985 for (int i=0; i<N && maxNum > 0; i++) {
4986 TaskRecord tr = mRecentTasks.get(i);
4987 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4988 || (tr.intent == null)
4989 || ((tr.intent.getFlags()
4990 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4991 ActivityManager.RecentTaskInfo rti
4992 = new ActivityManager.RecentTaskInfo();
4993 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08004994 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004995 rti.baseIntent = new Intent(
4996 tr.intent != null ? tr.intent : tr.affinityIntent);
4997 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08004998 rti.description = tr.lastDescription;
4999
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005000 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5001 // Check whether this activity is currently available.
5002 try {
5003 if (rti.origActivity != null) {
5004 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5005 continue;
5006 }
5007 } else if (rti.baseIntent != null) {
5008 if (pm.queryIntentActivities(rti.baseIntent,
5009 null, 0) == null) {
5010 continue;
5011 }
5012 }
5013 } catch (RemoteException e) {
5014 // Will never happen.
5015 }
5016 }
5017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 res.add(rti);
5019 maxNum--;
5020 }
5021 }
5022 return res;
5023 }
5024 }
5025
Dianne Hackbornd94df452011-02-16 18:53:31 -08005026 public Bitmap getTaskThumbnail(int id) {
5027 synchronized (this) {
5028 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5029 "getTaskThumbnail()");
5030 ActivityRecord resumed = mMainStack.mResumedActivity;
5031 final int N = mRecentTasks.size();
5032 for (int i=0; i<N; i++) {
5033 TaskRecord tr = mRecentTasks.get(i);
5034 if (tr.taskId == id) {
5035 if (resumed != null && resumed.task == tr) {
5036 return resumed.stack.screenshotActivities(resumed);
5037 } else {
5038 return tr.lastThumbnail;
5039 }
5040 }
5041 }
5042 }
5043 return null;
5044 }
5045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5047 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005048 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 TaskRecord jt = startTask;
5050
5051 // First look backwards
5052 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005053 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005054 if (r.task != jt) {
5055 jt = r.task;
5056 if (affinity.equals(jt.affinity)) {
5057 return j;
5058 }
5059 }
5060 }
5061
5062 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005063 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005064 jt = startTask;
5065 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005066 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005067 if (r.task != jt) {
5068 if (affinity.equals(jt.affinity)) {
5069 return j;
5070 }
5071 jt = r.task;
5072 }
5073 }
5074
5075 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005076 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 return N-1;
5078 }
5079
5080 return -1;
5081 }
5082
5083 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005084 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005085 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005086 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005087 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5088 "moveTaskToFront()");
5089
5090 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005091 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5092 Binder.getCallingUid(), "Task to front")) {
5093 return;
5094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005095 final long origId = Binder.clearCallingIdentity();
5096 try {
5097 int N = mRecentTasks.size();
5098 for (int i=0; i<N; i++) {
5099 TaskRecord tr = mRecentTasks.get(i);
5100 if (tr.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005101 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5102 mMainStack.mUserLeaving = true;
5103 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005104 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5105 // Caller wants the home activity moved with it. To accomplish this,
5106 // we'll just move the home task to the top first.
5107 mMainStack.moveHomeToFrontLocked();
5108 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005109 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 return;
5111 }
5112 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005113 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5114 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005116 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5117 mMainStack.mUserLeaving = true;
5118 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005119 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5120 // Caller wants the home activity moved with it. To accomplish this,
5121 // we'll just move the home task to the top first.
5122 mMainStack.moveHomeToFrontLocked();
5123 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005124 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005125 return;
5126 }
5127 }
5128 } finally {
5129 Binder.restoreCallingIdentity(origId);
5130 }
5131 }
5132 }
5133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134 public void moveTaskToBack(int task) {
5135 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5136 "moveTaskToBack()");
5137
5138 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005139 if (mMainStack.mResumedActivity != null
5140 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005141 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5142 Binder.getCallingUid(), "Task to back")) {
5143 return;
5144 }
5145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005146 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005147 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005148 Binder.restoreCallingIdentity(origId);
5149 }
5150 }
5151
5152 /**
5153 * Moves an activity, and all of the other activities within the same task, to the bottom
5154 * of the history stack. The activity's order within the task is unchanged.
5155 *
5156 * @param token A reference to the activity we wish to move
5157 * @param nonRoot If false then this only works if the activity is the root
5158 * of a task; if true it will work for any activity in a task.
5159 * @return Returns true if the move completed, false if not.
5160 */
5161 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5162 synchronized(this) {
5163 final long origId = Binder.clearCallingIdentity();
5164 int taskId = getTaskForActivityLocked(token, !nonRoot);
5165 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005166 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005167 }
5168 Binder.restoreCallingIdentity(origId);
5169 }
5170 return false;
5171 }
5172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005173 public void moveTaskBackwards(int task) {
5174 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5175 "moveTaskBackwards()");
5176
5177 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005178 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5179 Binder.getCallingUid(), "Task backwards")) {
5180 return;
5181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005182 final long origId = Binder.clearCallingIdentity();
5183 moveTaskBackwardsLocked(task);
5184 Binder.restoreCallingIdentity(origId);
5185 }
5186 }
5187
5188 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005189 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005190 }
5191
5192 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5193 synchronized(this) {
5194 return getTaskForActivityLocked(token, onlyRoot);
5195 }
5196 }
5197
5198 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005199 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 TaskRecord lastTask = null;
5201 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005202 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203 if (r == token) {
5204 if (!onlyRoot || lastTask != r.task) {
5205 return r.task.taskId;
5206 }
5207 return -1;
5208 }
5209 lastTask = r.task;
5210 }
5211
5212 return -1;
5213 }
5214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005215 public void finishOtherInstances(IBinder token, ComponentName className) {
5216 synchronized(this) {
5217 final long origId = Binder.clearCallingIdentity();
5218
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005219 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 TaskRecord lastTask = null;
5221 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005222 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223 if (r.realActivity.equals(className)
5224 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005225 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005226 null, "others")) {
5227 i--;
5228 N--;
5229 }
5230 }
5231 lastTask = r.task;
5232 }
5233
5234 Binder.restoreCallingIdentity(origId);
5235 }
5236 }
5237
5238 // =========================================================
5239 // THUMBNAILS
5240 // =========================================================
5241
5242 public void reportThumbnail(IBinder token,
5243 Bitmap thumbnail, CharSequence description) {
5244 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5245 final long origId = Binder.clearCallingIdentity();
5246 sendPendingThumbnail(null, token, thumbnail, description, true);
5247 Binder.restoreCallingIdentity(origId);
5248 }
5249
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005250 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251 Bitmap thumbnail, CharSequence description, boolean always) {
5252 TaskRecord task = null;
5253 ArrayList receivers = null;
5254
5255 //System.out.println("Send pending thumbnail: " + r);
5256
5257 synchronized(this) {
5258 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005259 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005260 if (index < 0) {
5261 return;
5262 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005263 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005264 }
5265 if (thumbnail == null) {
5266 thumbnail = r.thumbnail;
5267 description = r.description;
5268 }
5269 if (thumbnail == null && !always) {
5270 // If there is no thumbnail, and this entry is not actually
5271 // going away, then abort for now and pick up the next
5272 // thumbnail we get.
5273 return;
5274 }
5275 task = r.task;
5276
5277 int N = mPendingThumbnails.size();
5278 int i=0;
5279 while (i<N) {
5280 PendingThumbnailsRecord pr =
5281 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5282 //System.out.println("Looking in " + pr.pendingRecords);
5283 if (pr.pendingRecords.remove(r)) {
5284 if (receivers == null) {
5285 receivers = new ArrayList();
5286 }
5287 receivers.add(pr);
5288 if (pr.pendingRecords.size() == 0) {
5289 pr.finished = true;
5290 mPendingThumbnails.remove(i);
5291 N--;
5292 continue;
5293 }
5294 }
5295 i++;
5296 }
5297 }
5298
5299 if (receivers != null) {
5300 final int N = receivers.size();
5301 for (int i=0; i<N; i++) {
5302 try {
5303 PendingThumbnailsRecord pr =
5304 (PendingThumbnailsRecord)receivers.get(i);
5305 pr.receiver.newThumbnail(
5306 task != null ? task.taskId : -1, thumbnail, description);
5307 if (pr.finished) {
5308 pr.receiver.finished();
5309 }
5310 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005311 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 }
5313 }
5314 }
5315 }
5316
5317 // =========================================================
5318 // CONTENT PROVIDERS
5319 // =========================================================
5320
5321 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5322 List providers = null;
5323 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005324 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005325 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005326 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005327 } catch (RemoteException ex) {
5328 }
5329 if (providers != null) {
5330 final int N = providers.size();
5331 for (int i=0; i<N; i++) {
5332 ProviderInfo cpi =
5333 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005334 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 if (cpr == null) {
5336 cpr = new ContentProviderRecord(cpi, app.info);
5337 mProvidersByClass.put(cpi.name, cpr);
5338 }
5339 app.pubProviders.put(cpi.name, cpr);
5340 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005341 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 }
5343 }
5344 return providers;
5345 }
5346
5347 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005348 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5350 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5351 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005352 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005353 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 return null;
5355 }
5356 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005357 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 == PackageManager.PERMISSION_GRANTED) {
5359 return null;
5360 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005361
5362 PathPermission[] pps = cpi.pathPermissions;
5363 if (pps != null) {
5364 int i = pps.length;
5365 while (i > 0) {
5366 i--;
5367 PathPermission pp = pps[i];
5368 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005369 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005370 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005371 return null;
5372 }
5373 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005374 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005375 == PackageManager.PERMISSION_GRANTED) {
5376 return null;
5377 }
5378 }
5379 }
5380
Dianne Hackbornb424b632010-08-18 15:59:05 -07005381 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5382 if (perms != null) {
5383 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5384 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5385 return null;
5386 }
5387 }
5388 }
5389
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005390 String msg;
5391 if (!cpi.exported) {
5392 msg = "Permission Denial: opening provider " + cpi.name
5393 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5394 + ", uid=" + callingUid + ") that is not exported from uid "
5395 + cpi.applicationInfo.uid;
5396 } else {
5397 msg = "Permission Denial: opening provider " + cpi.name
5398 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5399 + ", uid=" + callingUid + ") requires "
5400 + cpi.readPermission + " or " + cpi.writePermission;
5401 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005402 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005403 return msg;
5404 }
5405
5406 private final ContentProviderHolder getContentProviderImpl(
5407 IApplicationThread caller, String name) {
5408 ContentProviderRecord cpr;
5409 ProviderInfo cpi = null;
5410
5411 synchronized(this) {
5412 ProcessRecord r = null;
5413 if (caller != null) {
5414 r = getRecordForAppLocked(caller);
5415 if (r == null) {
5416 throw new SecurityException(
5417 "Unable to find app for caller " + caller
5418 + " (pid=" + Binder.getCallingPid()
5419 + ") when getting content provider " + name);
5420 }
5421 }
5422
5423 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005424 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005425 if (cpr != null) {
5426 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005427 String msg;
5428 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5429 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005430 }
5431
5432 if (r != null && cpr.canRunHere(r)) {
5433 // This provider has been published or is in the process
5434 // of being published... but it is also allowed to run
5435 // in the caller's process, so don't make a connection
5436 // and just let the caller instantiate its own instance.
5437 if (cpr.provider != null) {
5438 // don't give caller the provider object, it needs
5439 // to make its own.
5440 cpr = new ContentProviderRecord(cpr);
5441 }
5442 return cpr;
5443 }
5444
5445 final long origId = Binder.clearCallingIdentity();
5446
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005447 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005448 // return it right away.
5449 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005450 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005451 "Adding provider requested by "
5452 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005453 + cpr.info.processName);
5454 Integer cnt = r.conProviders.get(cpr);
5455 if (cnt == null) {
5456 r.conProviders.put(cpr, new Integer(1));
5457 } else {
5458 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005460 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005461 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5462 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005463 // make sure to count it as being accessed and thus
5464 // back up on the LRU list. This is good because
5465 // content providers are often expensive to start.
5466 updateLruProcessLocked(cpr.app, false, true);
5467 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005468 } else {
5469 cpr.externals++;
5470 }
5471
5472 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005473 updateOomAdjLocked(cpr.app);
5474 }
5475
5476 Binder.restoreCallingIdentity(origId);
5477
5478 } else {
5479 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005480 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005481 resolveContentProvider(name,
5482 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005483 } catch (RemoteException ex) {
5484 }
5485 if (cpi == null) {
5486 return null;
5487 }
5488
Dianne Hackbornb424b632010-08-18 15:59:05 -07005489 String msg;
5490 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5491 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005492 }
5493
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005494 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005495 && !cpi.processName.equals("system")) {
5496 // If this content provider does not run in the system
5497 // process, and the system is not yet ready to run other
5498 // processes, then fail fast instead of hanging.
5499 throw new IllegalArgumentException(
5500 "Attempt to launch content provider before system ready");
5501 }
5502
Dianne Hackborn860755f2010-06-03 18:47:52 -07005503 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 final boolean firstClass = cpr == null;
5505 if (firstClass) {
5506 try {
5507 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005508 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 getApplicationInfo(
5510 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005511 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005512 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005513 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 + cpi.name);
5515 return null;
5516 }
5517 cpr = new ContentProviderRecord(cpi, ai);
5518 } catch (RemoteException ex) {
5519 // pm is in same process, this will never happen.
5520 }
5521 }
5522
5523 if (r != null && cpr.canRunHere(r)) {
5524 // If this is a multiprocess provider, then just return its
5525 // info and allow the caller to instantiate it. Only do
5526 // this if the provider is the same user as the caller's
5527 // process, or can run as root (so can be in any process).
5528 return cpr;
5529 }
5530
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005531 if (DEBUG_PROVIDER) {
5532 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005533 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005534 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005535 }
5536
5537 // This is single process, and our app is now connecting to it.
5538 // See if we are already in the process of launching this
5539 // provider.
5540 final int N = mLaunchingProviders.size();
5541 int i;
5542 for (i=0; i<N; i++) {
5543 if (mLaunchingProviders.get(i) == cpr) {
5544 break;
5545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005546 }
5547
5548 // If the provider is not already being launched, then get it
5549 // started.
5550 if (i >= N) {
5551 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005552
5553 try {
5554 // Content provider is now in use, its package can't be stopped.
5555 try {
5556 AppGlobals.getPackageManager().setPackageStoppedState(
5557 cpr.appInfo.packageName, false);
5558 } catch (RemoteException e) {
5559 }
5560
5561 ProcessRecord proc = startProcessLocked(cpi.processName,
5562 cpr.appInfo, false, 0, "content provider",
5563 new ComponentName(cpi.applicationInfo.packageName,
5564 cpi.name), false);
5565 if (proc == null) {
5566 Slog.w(TAG, "Unable to launch app "
5567 + cpi.applicationInfo.packageName + "/"
5568 + cpi.applicationInfo.uid + " for provider "
5569 + name + ": process is bad");
5570 return null;
5571 }
5572 cpr.launchingApp = proc;
5573 mLaunchingProviders.add(cpr);
5574 } finally {
5575 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005577 }
5578
5579 // Make sure the provider is published (the same provider class
5580 // may be published under multiple names).
5581 if (firstClass) {
5582 mProvidersByClass.put(cpi.name, cpr);
5583 }
5584 mProvidersByName.put(name, cpr);
5585
5586 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005587 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005588 "Adding provider requested by "
5589 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005590 + cpr.info.processName);
5591 Integer cnt = r.conProviders.get(cpr);
5592 if (cnt == null) {
5593 r.conProviders.put(cpr, new Integer(1));
5594 } else {
5595 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5596 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 cpr.clients.add(r);
5598 } else {
5599 cpr.externals++;
5600 }
5601 }
5602 }
5603
5604 // Wait for the provider to be published...
5605 synchronized (cpr) {
5606 while (cpr.provider == null) {
5607 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005608 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005609 + cpi.applicationInfo.packageName + "/"
5610 + cpi.applicationInfo.uid + " for provider "
5611 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005612 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 cpi.applicationInfo.packageName,
5614 cpi.applicationInfo.uid, name);
5615 return null;
5616 }
5617 try {
5618 cpr.wait();
5619 } catch (InterruptedException ex) {
5620 }
5621 }
5622 }
5623 return cpr;
5624 }
5625
5626 public final ContentProviderHolder getContentProvider(
5627 IApplicationThread caller, String name) {
5628 if (caller == null) {
5629 String msg = "null IApplicationThread when getting content provider "
5630 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005631 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005632 throw new SecurityException(msg);
5633 }
5634
5635 return getContentProviderImpl(caller, name);
5636 }
5637
5638 private ContentProviderHolder getContentProviderExternal(String name) {
5639 return getContentProviderImpl(null, name);
5640 }
5641
5642 /**
5643 * Drop a content provider from a ProcessRecord's bookkeeping
5644 * @param cpr
5645 */
5646 public void removeContentProvider(IApplicationThread caller, String name) {
5647 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005648 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005650 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005651 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005652 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005653 return;
5654 }
5655 final ProcessRecord r = getRecordForAppLocked(caller);
5656 if (r == null) {
5657 throw new SecurityException(
5658 "Unable to find app for caller " + caller +
5659 " when removing content provider " + name);
5660 }
5661 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005662 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005663 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005664 + r.info.processName + " from process "
5665 + localCpr.appInfo.processName);
5666 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005667 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005668 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005669 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005670 return;
5671 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005672 Integer cnt = r.conProviders.get(localCpr);
5673 if (cnt == null || cnt.intValue() <= 1) {
5674 localCpr.clients.remove(r);
5675 r.conProviders.remove(localCpr);
5676 } else {
5677 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 }
5680 updateOomAdjLocked();
5681 }
5682 }
5683
5684 private void removeContentProviderExternal(String name) {
5685 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005686 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005687 if(cpr == null) {
5688 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005689 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005690 return;
5691 }
5692
5693 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005694 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005695 localCpr.externals--;
5696 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005697 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005698 }
5699 updateOomAdjLocked();
5700 }
5701 }
5702
5703 public final void publishContentProviders(IApplicationThread caller,
5704 List<ContentProviderHolder> providers) {
5705 if (providers == null) {
5706 return;
5707 }
5708
5709 synchronized(this) {
5710 final ProcessRecord r = getRecordForAppLocked(caller);
5711 if (r == null) {
5712 throw new SecurityException(
5713 "Unable to find app for caller " + caller
5714 + " (pid=" + Binder.getCallingPid()
5715 + ") when publishing content providers");
5716 }
5717
5718 final long origId = Binder.clearCallingIdentity();
5719
5720 final int N = providers.size();
5721 for (int i=0; i<N; i++) {
5722 ContentProviderHolder src = providers.get(i);
5723 if (src == null || src.info == null || src.provider == null) {
5724 continue;
5725 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005726 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005727 if (dst != null) {
5728 mProvidersByClass.put(dst.info.name, dst);
5729 String names[] = dst.info.authority.split(";");
5730 for (int j = 0; j < names.length; j++) {
5731 mProvidersByName.put(names[j], dst);
5732 }
5733
5734 int NL = mLaunchingProviders.size();
5735 int j;
5736 for (j=0; j<NL; j++) {
5737 if (mLaunchingProviders.get(j) == dst) {
5738 mLaunchingProviders.remove(j);
5739 j--;
5740 NL--;
5741 }
5742 }
5743 synchronized (dst) {
5744 dst.provider = src.provider;
5745 dst.app = r;
5746 dst.notifyAll();
5747 }
5748 updateOomAdjLocked(r);
5749 }
5750 }
5751
5752 Binder.restoreCallingIdentity(origId);
5753 }
5754 }
5755
5756 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005757 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005758 synchronized (mSelf) {
5759 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5760 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005761 if (providers != null) {
5762 for (int i=providers.size()-1; i>=0; i--) {
5763 ProviderInfo pi = (ProviderInfo)providers.get(i);
5764 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5765 Slog.w(TAG, "Not installing system proc provider " + pi.name
5766 + ": not system .apk");
5767 providers.remove(i);
5768 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005769 }
5770 }
5771 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005772 if (providers != null) {
5773 mSystemThread.installSystemProviders(providers);
5774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005775 }
5776
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005777 /**
5778 * Allows app to retrieve the MIME type of a URI without having permission
5779 * to access its content provider.
5780 *
5781 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5782 *
5783 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5784 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5785 */
5786 public String getProviderMimeType(Uri uri) {
5787 final String name = uri.getAuthority();
5788 final long ident = Binder.clearCallingIdentity();
5789 ContentProviderHolder holder = null;
5790
5791 try {
5792 holder = getContentProviderExternal(name);
5793 if (holder != null) {
5794 return holder.provider.getType(uri);
5795 }
5796 } catch (RemoteException e) {
5797 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5798 return null;
5799 } finally {
5800 if (holder != null) {
5801 removeContentProviderExternal(name);
5802 }
5803 Binder.restoreCallingIdentity(ident);
5804 }
5805
5806 return null;
5807 }
5808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005809 // =========================================================
5810 // GLOBAL MANAGEMENT
5811 // =========================================================
5812
5813 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5814 ApplicationInfo info, String customProcess) {
5815 String proc = customProcess != null ? customProcess : info.processName;
5816 BatteryStatsImpl.Uid.Proc ps = null;
5817 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5818 synchronized (stats) {
5819 ps = stats.getProcessStatsLocked(info.uid, proc);
5820 }
5821 return new ProcessRecord(ps, thread, info, proc);
5822 }
5823
5824 final ProcessRecord addAppLocked(ApplicationInfo info) {
5825 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5826
5827 if (app == null) {
5828 app = newProcessRecordLocked(null, info, null);
5829 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005830 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005831 }
5832
Dianne Hackborne7f97212011-02-24 14:40:20 -08005833 // This package really, really can not be stopped.
5834 try {
5835 AppGlobals.getPackageManager().setPackageStoppedState(
5836 info.packageName, false);
5837 } catch (RemoteException e) {
5838 }
5839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5841 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5842 app.persistent = true;
5843 app.maxAdj = CORE_SERVER_ADJ;
5844 }
5845 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5846 mPersistentStartingProcesses.add(app);
5847 startProcessLocked(app, "added application", app.processName);
5848 }
5849
5850 return app;
5851 }
5852
5853 public void unhandledBack() {
5854 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5855 "unhandledBack()");
5856
5857 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005858 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005859 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 TAG, "Performing unhandledBack(): stack size = " + count);
5861 if (count > 1) {
5862 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005863 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005864 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5865 Binder.restoreCallingIdentity(origId);
5866 }
5867 }
5868 }
5869
5870 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5871 String name = uri.getAuthority();
5872 ContentProviderHolder cph = getContentProviderExternal(name);
5873 ParcelFileDescriptor pfd = null;
5874 if (cph != null) {
5875 // We record the binder invoker's uid in thread-local storage before
5876 // going to the content provider to open the file. Later, in the code
5877 // that handles all permissions checks, we look for this uid and use
5878 // that rather than the Activity Manager's own uid. The effect is that
5879 // we do the check against the caller's permissions even though it looks
5880 // to the content provider like the Activity Manager itself is making
5881 // the request.
5882 sCallerIdentity.set(new Identity(
5883 Binder.getCallingPid(), Binder.getCallingUid()));
5884 try {
5885 pfd = cph.provider.openFile(uri, "r");
5886 } catch (FileNotFoundException e) {
5887 // do nothing; pfd will be returned null
5888 } finally {
5889 // Ensure that whatever happens, we clean up the identity state
5890 sCallerIdentity.remove();
5891 }
5892
5893 // We've got the fd now, so we're done with the provider.
5894 removeContentProviderExternal(name);
5895 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005896 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 }
5898 return pfd;
5899 }
5900
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005901 // Actually is sleeping or shutting down or whatever else in the future
5902 // is an inactive state.
5903 public boolean isSleeping() {
5904 return mSleeping || mShuttingDown;
5905 }
5906
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 public void goingToSleep() {
5908 synchronized(this) {
5909 mSleeping = true;
5910 mWindowManager.setEventDispatching(false);
5911
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005912 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005913
5914 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005915 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005916 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5917 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005918 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005919 }
5920 }
5921
Dianne Hackborn55280a92009-05-07 15:53:46 -07005922 public boolean shutdown(int timeout) {
5923 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5924 != PackageManager.PERMISSION_GRANTED) {
5925 throw new SecurityException("Requires permission "
5926 + android.Manifest.permission.SHUTDOWN);
5927 }
5928
5929 boolean timedout = false;
5930
5931 synchronized(this) {
5932 mShuttingDown = true;
5933 mWindowManager.setEventDispatching(false);
5934
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005935 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005936 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005937 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005938 while (mMainStack.mResumedActivity != null
5939 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005940 long delay = endTime - System.currentTimeMillis();
5941 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005942 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005943 timedout = true;
5944 break;
5945 }
5946 try {
5947 this.wait();
5948 } catch (InterruptedException e) {
5949 }
5950 }
5951 }
5952 }
5953
5954 mUsageStatsService.shutdown();
5955 mBatteryStatsService.shutdown();
5956
5957 return timedout;
5958 }
5959
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005960 public final void activitySlept(IBinder token) {
5961 if (localLOGV) Slog.v(
5962 TAG, "Activity slept: token=" + token);
5963
5964 ActivityRecord r = null;
5965
5966 final long origId = Binder.clearCallingIdentity();
5967
5968 synchronized (this) {
5969 int index = mMainStack.indexOfTokenLocked(token);
5970 if (index >= 0) {
5971 r = (ActivityRecord)mMainStack.mHistory.get(index);
5972 mMainStack.activitySleptLocked(r);
5973 }
5974 }
5975
5976 Binder.restoreCallingIdentity(origId);
5977 }
5978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005979 public void wakingUp() {
5980 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005981 mWindowManager.setEventDispatching(true);
5982 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005983 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005984 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005985 }
5986 }
5987
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005988 public void stopAppSwitches() {
5989 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5990 != PackageManager.PERMISSION_GRANTED) {
5991 throw new SecurityException("Requires permission "
5992 + android.Manifest.permission.STOP_APP_SWITCHES);
5993 }
5994
5995 synchronized(this) {
5996 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5997 + APP_SWITCH_DELAY_TIME;
5998 mDidAppSwitch = false;
5999 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6000 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6001 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6002 }
6003 }
6004
6005 public void resumeAppSwitches() {
6006 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6007 != PackageManager.PERMISSION_GRANTED) {
6008 throw new SecurityException("Requires permission "
6009 + android.Manifest.permission.STOP_APP_SWITCHES);
6010 }
6011
6012 synchronized(this) {
6013 // Note that we don't execute any pending app switches... we will
6014 // let those wait until either the timeout, or the next start
6015 // activity request.
6016 mAppSwitchesAllowedTime = 0;
6017 }
6018 }
6019
6020 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6021 String name) {
6022 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6023 return true;
6024 }
6025
6026 final int perm = checkComponentPermission(
6027 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006028 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006029 if (perm == PackageManager.PERMISSION_GRANTED) {
6030 return true;
6031 }
6032
Joe Onorato8a9b2202010-02-26 18:56:32 -08006033 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006034 return false;
6035 }
6036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006037 public void setDebugApp(String packageName, boolean waitForDebugger,
6038 boolean persistent) {
6039 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6040 "setDebugApp()");
6041
6042 // Note that this is not really thread safe if there are multiple
6043 // callers into it at the same time, but that's not a situation we
6044 // care about.
6045 if (persistent) {
6046 final ContentResolver resolver = mContext.getContentResolver();
6047 Settings.System.putString(
6048 resolver, Settings.System.DEBUG_APP,
6049 packageName);
6050 Settings.System.putInt(
6051 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6052 waitForDebugger ? 1 : 0);
6053 }
6054
6055 synchronized (this) {
6056 if (!persistent) {
6057 mOrigDebugApp = mDebugApp;
6058 mOrigWaitForDebugger = mWaitForDebugger;
6059 }
6060 mDebugApp = packageName;
6061 mWaitForDebugger = waitForDebugger;
6062 mDebugTransient = !persistent;
6063 if (packageName != null) {
6064 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006065 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006066 Binder.restoreCallingIdentity(origId);
6067 }
6068 }
6069 }
6070
6071 public void setAlwaysFinish(boolean enabled) {
6072 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6073 "setAlwaysFinish()");
6074
6075 Settings.System.putInt(
6076 mContext.getContentResolver(),
6077 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6078
6079 synchronized (this) {
6080 mAlwaysFinishActivities = enabled;
6081 }
6082 }
6083
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006084 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006085 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006086 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006087 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006088 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006089 }
6090 }
6091
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006092 public boolean isUserAMonkey() {
6093 // For now the fact that there is a controller implies
6094 // we have a monkey.
6095 synchronized (this) {
6096 return mController != null;
6097 }
6098 }
6099
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006100 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006101 synchronized (this) {
6102 mWatchers.register(watcher);
6103 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006104 }
6105
6106 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006107 synchronized (this) {
6108 mWatchers.unregister(watcher);
6109 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006110 }
6111
Daniel Sandler69a48172010-06-23 16:29:36 -04006112 public void setImmersive(IBinder token, boolean immersive) {
6113 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006114 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006115 if (index < 0) {
6116 throw new IllegalArgumentException();
6117 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006118 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006119 r.immersive = immersive;
6120 }
6121 }
6122
6123 public boolean isImmersive(IBinder token) {
6124 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006125 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006126 if (index < 0) {
6127 throw new IllegalArgumentException();
6128 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006129 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006130 return r.immersive;
6131 }
6132 }
6133
6134 public boolean isTopActivityImmersive() {
6135 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006136 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006137 return (r != null) ? r.immersive : false;
6138 }
6139 }
6140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006141 public final void enterSafeMode() {
6142 synchronized(this) {
6143 // It only makes sense to do this before the system is ready
6144 // and started launching other packages.
6145 if (!mSystemReady) {
6146 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006147 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006148 } catch (RemoteException e) {
6149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006150 }
6151 }
6152 }
6153
Jeff Brownb09abc12011-01-13 21:08:27 -08006154 public final void showSafeModeOverlay() {
6155 View v = LayoutInflater.from(mContext).inflate(
6156 com.android.internal.R.layout.safe_mode, null);
6157 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6158 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6159 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6160 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6161 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6162 lp.format = v.getBackground().getOpacity();
6163 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6164 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6165 ((WindowManager)mContext.getSystemService(
6166 Context.WINDOW_SERVICE)).addView(v, lp);
6167 }
6168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006169 public void noteWakeupAlarm(IIntentSender sender) {
6170 if (!(sender instanceof PendingIntentRecord)) {
6171 return;
6172 }
6173 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6174 synchronized (stats) {
6175 if (mBatteryStatsService.isOnBattery()) {
6176 mBatteryStatsService.enforceCallingPermission();
6177 PendingIntentRecord rec = (PendingIntentRecord)sender;
6178 int MY_UID = Binder.getCallingUid();
6179 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6180 BatteryStatsImpl.Uid.Pkg pkg =
6181 stats.getPackageStatsLocked(uid, rec.key.packageName);
6182 pkg.incWakeupsLocked();
6183 }
6184 }
6185 }
6186
Dianne Hackborn64825172011-03-02 21:32:58 -08006187 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006188 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006189 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006190 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006191 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006192 // XXX Note: don't acquire main activity lock here, because the window
6193 // manager calls in with its locks held.
6194
6195 boolean killed = false;
6196 synchronized (mPidsSelfLocked) {
6197 int[] types = new int[pids.length];
6198 int worstType = 0;
6199 for (int i=0; i<pids.length; i++) {
6200 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6201 if (proc != null) {
6202 int type = proc.setAdj;
6203 types[i] = type;
6204 if (type > worstType) {
6205 worstType = type;
6206 }
6207 }
6208 }
6209
Dianne Hackborn64825172011-03-02 21:32:58 -08006210 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006211 // then constrain it so we will kill all hidden procs.
6212 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6213 worstType = HIDDEN_APP_MIN_ADJ;
6214 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006215
6216 // If this is not a secure call, don't let it kill processes that
6217 // are important.
6218 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6219 worstType = SECONDARY_SERVER_ADJ;
6220 }
6221
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006222 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006223 for (int i=0; i<pids.length; i++) {
6224 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6225 if (proc == null) {
6226 continue;
6227 }
6228 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006229 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006230 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006231 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6232 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006233 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006234 proc.killedBackground = true;
6235 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006236 }
6237 }
6238 }
6239 return killed;
6240 }
6241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006242 public final void startRunning(String pkg, String cls, String action,
6243 String data) {
6244 synchronized(this) {
6245 if (mStartRunning) {
6246 return;
6247 }
6248 mStartRunning = true;
6249 mTopComponent = pkg != null && cls != null
6250 ? new ComponentName(pkg, cls) : null;
6251 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6252 mTopData = data;
6253 if (!mSystemReady) {
6254 return;
6255 }
6256 }
6257
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006258 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006259 }
6260
6261 private void retrieveSettings() {
6262 final ContentResolver resolver = mContext.getContentResolver();
6263 String debugApp = Settings.System.getString(
6264 resolver, Settings.System.DEBUG_APP);
6265 boolean waitForDebugger = Settings.System.getInt(
6266 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6267 boolean alwaysFinishActivities = Settings.System.getInt(
6268 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6269
6270 Configuration configuration = new Configuration();
6271 Settings.System.getConfiguration(resolver, configuration);
6272
6273 synchronized (this) {
6274 mDebugApp = mOrigDebugApp = debugApp;
6275 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6276 mAlwaysFinishActivities = alwaysFinishActivities;
6277 // This happens before any activities are started, so we can
6278 // change mConfiguration in-place.
6279 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006280 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006281 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006282 }
6283 }
6284
6285 public boolean testIsSystemReady() {
6286 // no need to synchronize(this) just to read & return the value
6287 return mSystemReady;
6288 }
6289
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006290 private static File getCalledPreBootReceiversFile() {
6291 File dataDir = Environment.getDataDirectory();
6292 File systemDir = new File(dataDir, "system");
6293 File fname = new File(systemDir, "called_pre_boots.dat");
6294 return fname;
6295 }
6296
6297 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6298 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6299 File file = getCalledPreBootReceiversFile();
6300 FileInputStream fis = null;
6301 try {
6302 fis = new FileInputStream(file);
6303 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6304 int vers = dis.readInt();
6305 String codename = dis.readUTF();
6306 if (vers == android.os.Build.VERSION.SDK_INT
6307 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6308 int num = dis.readInt();
6309 while (num > 0) {
6310 num--;
6311 String pkg = dis.readUTF();
6312 String cls = dis.readUTF();
6313 lastDoneReceivers.add(new ComponentName(pkg, cls));
6314 }
6315 }
6316 } catch (FileNotFoundException e) {
6317 } catch (IOException e) {
6318 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6319 } finally {
6320 if (fis != null) {
6321 try {
6322 fis.close();
6323 } catch (IOException e) {
6324 }
6325 }
6326 }
6327 return lastDoneReceivers;
6328 }
6329
6330 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6331 File file = getCalledPreBootReceiversFile();
6332 FileOutputStream fos = null;
6333 DataOutputStream dos = null;
6334 try {
6335 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6336 fos = new FileOutputStream(file);
6337 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6338 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6339 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6340 dos.writeInt(list.size());
6341 for (int i=0; i<list.size(); i++) {
6342 dos.writeUTF(list.get(i).getPackageName());
6343 dos.writeUTF(list.get(i).getClassName());
6344 }
6345 } catch (IOException e) {
6346 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6347 file.delete();
6348 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006349 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006350 if (dos != null) {
6351 try {
6352 dos.close();
6353 } catch (IOException e) {
6354 // TODO Auto-generated catch block
6355 e.printStackTrace();
6356 }
6357 }
6358 }
6359 }
6360
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006361 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006362 // In the simulator, startRunning will never have been called, which
6363 // normally sets a few crucial variables. Do it here instead.
6364 if (!Process.supportsProcesses()) {
6365 mStartRunning = true;
6366 mTopAction = Intent.ACTION_MAIN;
6367 }
6368
6369 synchronized(this) {
6370 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006371 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 return;
6373 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006374
6375 // Check to see if there are any update receivers to run.
6376 if (!mDidUpdate) {
6377 if (mWaitingUpdate) {
6378 return;
6379 }
6380 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6381 List<ResolveInfo> ris = null;
6382 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006383 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006384 intent, null, 0);
6385 } catch (RemoteException e) {
6386 }
6387 if (ris != null) {
6388 for (int i=ris.size()-1; i>=0; i--) {
6389 if ((ris.get(i).activityInfo.applicationInfo.flags
6390 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6391 ris.remove(i);
6392 }
6393 }
6394 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006395
6396 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6397
6398 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006399 for (int i=0; i<ris.size(); i++) {
6400 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006401 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6402 if (lastDoneReceivers.contains(comp)) {
6403 ris.remove(i);
6404 i--;
6405 }
6406 }
6407
6408 for (int i=0; i<ris.size(); i++) {
6409 ActivityInfo ai = ris.get(i).activityInfo;
6410 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6411 doneReceivers.add(comp);
6412 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006413 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006414 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006415 finisher = new IIntentReceiver.Stub() {
6416 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006417 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006418 boolean sticky) {
6419 // The raw IIntentReceiver interface is called
6420 // with the AM lock held, so redispatch to
6421 // execute our code without the lock.
6422 mHandler.post(new Runnable() {
6423 public void run() {
6424 synchronized (ActivityManagerService.this) {
6425 mDidUpdate = true;
6426 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006427 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006428 systemReady(goingCallback);
6429 }
6430 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006431 }
6432 };
6433 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006434 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006435 broadcastIntentLocked(null, null, intent, null, finisher,
6436 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006437 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006438 mWaitingUpdate = true;
6439 }
6440 }
6441 }
6442 if (mWaitingUpdate) {
6443 return;
6444 }
6445 mDidUpdate = true;
6446 }
6447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006448 mSystemReady = true;
6449 if (!mStartRunning) {
6450 return;
6451 }
6452 }
6453
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006454 ArrayList<ProcessRecord> procsToKill = null;
6455 synchronized(mPidsSelfLocked) {
6456 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6457 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6458 if (!isAllowedWhileBooting(proc.info)){
6459 if (procsToKill == null) {
6460 procsToKill = new ArrayList<ProcessRecord>();
6461 }
6462 procsToKill.add(proc);
6463 }
6464 }
6465 }
6466
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006467 synchronized(this) {
6468 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006469 for (int i=procsToKill.size()-1; i>=0; i--) {
6470 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006471 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006472 removeProcessLocked(proc, true);
6473 }
6474 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006475
6476 // Now that we have cleaned up any update processes, we
6477 // are ready to start launching real processes and know that
6478 // we won't trample on them any more.
6479 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006480 }
6481
Joe Onorato8a9b2202010-02-26 18:56:32 -08006482 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006483 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006484 SystemClock.uptimeMillis());
6485
6486 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006487 // Make sure we have no pre-ready processes sitting around.
6488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006489 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6490 ResolveInfo ri = mContext.getPackageManager()
6491 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006492 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006493 CharSequence errorMsg = null;
6494 if (ri != null) {
6495 ActivityInfo ai = ri.activityInfo;
6496 ApplicationInfo app = ai.applicationInfo;
6497 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6498 mTopAction = Intent.ACTION_FACTORY_TEST;
6499 mTopData = null;
6500 mTopComponent = new ComponentName(app.packageName,
6501 ai.name);
6502 } else {
6503 errorMsg = mContext.getResources().getText(
6504 com.android.internal.R.string.factorytest_not_system);
6505 }
6506 } else {
6507 errorMsg = mContext.getResources().getText(
6508 com.android.internal.R.string.factorytest_no_action);
6509 }
6510 if (errorMsg != null) {
6511 mTopAction = null;
6512 mTopData = null;
6513 mTopComponent = null;
6514 Message msg = Message.obtain();
6515 msg.what = SHOW_FACTORY_ERROR_MSG;
6516 msg.getData().putCharSequence("msg", errorMsg);
6517 mHandler.sendMessage(msg);
6518 }
6519 }
6520 }
6521
6522 retrieveSettings();
6523
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006524 if (goingCallback != null) goingCallback.run();
6525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006526 synchronized (this) {
6527 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6528 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006529 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006530 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006531 if (apps != null) {
6532 int N = apps.size();
6533 int i;
6534 for (i=0; i<N; i++) {
6535 ApplicationInfo info
6536 = (ApplicationInfo)apps.get(i);
6537 if (info != null &&
6538 !info.packageName.equals("android")) {
6539 addAppLocked(info);
6540 }
6541 }
6542 }
6543 } catch (RemoteException ex) {
6544 // pm is in same process, this will never happen.
6545 }
6546 }
6547
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006548 // Start up initial activity.
6549 mBooting = true;
6550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006551 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006552 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006553 Message msg = Message.obtain();
6554 msg.what = SHOW_UID_ERROR_MSG;
6555 mHandler.sendMessage(msg);
6556 }
6557 } catch (RemoteException e) {
6558 }
6559
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006560 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006561 }
6562 }
6563
Dan Egnorb7f03672009-12-09 16:22:32 -08006564 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006565 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006567 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006568 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006569 startAppProblemLocked(app);
6570 app.stopFreezingAllLocked();
6571 return handleAppCrashLocked(app);
6572 }
6573
Dan Egnorb7f03672009-12-09 16:22:32 -08006574 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006575 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006576 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006577 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006578 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6579 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006580 startAppProblemLocked(app);
6581 app.stopFreezingAllLocked();
6582 }
6583
6584 /**
6585 * Generate a process error record, suitable for attachment to a ProcessRecord.
6586 *
6587 * @param app The ProcessRecord in which the error occurred.
6588 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6589 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006590 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006591 * @param shortMsg Short message describing the crash.
6592 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006593 * @param stackTrace Full crash stack trace, may be null.
6594 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006595 * @return Returns a fully-formed AppErrorStateInfo record.
6596 */
6597 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006598 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006599 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006601 report.condition = condition;
6602 report.processName = app.processName;
6603 report.pid = app.pid;
6604 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006605 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006606 report.shortMsg = shortMsg;
6607 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006608 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006609
6610 return report;
6611 }
6612
Dan Egnor42471dd2010-01-07 17:25:22 -08006613 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006614 synchronized (this) {
6615 app.crashing = false;
6616 app.crashingReport = null;
6617 app.notResponding = false;
6618 app.notRespondingReport = null;
6619 if (app.anrDialog == fromDialog) {
6620 app.anrDialog = null;
6621 }
6622 if (app.waitDialog == fromDialog) {
6623 app.waitDialog = null;
6624 }
6625 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006626 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006627 Slog.i(ActivityManagerService.TAG, "Killing "
6628 + app.processName + " (pid=" + app.pid + "): user's request");
6629 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6630 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006631 Process.killProcess(app.pid);
6632 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006633 }
6634 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006635
Dan Egnorb7f03672009-12-09 16:22:32 -08006636 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006637 long now = SystemClock.uptimeMillis();
6638
6639 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6640 app.info.uid);
6641 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6642 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006643 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006644 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006645 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006646 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006647 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6648 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006649 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006650 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006651 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006652 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006653 }
6654 }
6655 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006656 // Don't let services in this process be restarted and potentially
6657 // annoy the user repeatedly. Unless it is persistent, since those
6658 // processes run critical code.
6659 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006660 // We don't want to start this process again until the user
6661 // explicitly does so... but for persistent process, we really
6662 // need to keep it running. If a persistent process is actually
6663 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006664 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006665 app.info.processName);
6666 mBadProcesses.put(app.info.processName, app.info.uid, now);
6667 app.bad = true;
6668 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6669 app.removed = true;
6670 removeProcessLocked(app, false);
6671 return false;
6672 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006673 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006674 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006675 if (r.app == app) {
6676 // If the top running activity is from this crashing
6677 // process, then terminate it to avoid getting in a loop.
6678 Slog.w(TAG, " Force finishing activity "
6679 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006680 int index = mMainStack.indexOfTokenLocked(r);
6681 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006682 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006683 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006684 // stopped, to avoid a situation where one will get
6685 // re-start our crashing activity once it gets resumed again.
6686 index--;
6687 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006688 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006689 if (r.state == ActivityState.RESUMED
6690 || r.state == ActivityState.PAUSING
6691 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006692 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006693 Slog.w(TAG, " Force finishing activity "
6694 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006695 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006696 Activity.RESULT_CANCELED, null, "crashed");
6697 }
6698 }
6699 }
6700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006701 }
6702
6703 // Bump up the crash count of any services currently running in the proc.
6704 if (app.services.size() != 0) {
6705 // Any services running in the application need to be placed
6706 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006707 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006708 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006709 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006710 sr.crashCount++;
6711 }
6712 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006713
6714 // If the crashing process is what we consider to be the "home process" and it has been
6715 // replaced by a third-party app, clear the package preferred activities from packages
6716 // with a home activity running in the process to prevent a repeatedly crashing app
6717 // from blocking the user to manually clear the list.
6718 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6719 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6720 Iterator it = mHomeProcess.activities.iterator();
6721 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006722 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006723 if (r.isHomeActivity) {
6724 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6725 try {
6726 ActivityThread.getPackageManager()
6727 .clearPackagePreferredActivities(r.packageName);
6728 } catch (RemoteException c) {
6729 // pm is in same process, this will never happen.
6730 }
6731 }
6732 }
6733 }
6734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006735 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6736 return true;
6737 }
6738
6739 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006740 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6741 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006742 skipCurrentReceiverLocked(app);
6743 }
6744
6745 void skipCurrentReceiverLocked(ProcessRecord app) {
6746 boolean reschedule = false;
6747 BroadcastRecord r = app.curReceiver;
6748 if (r != null) {
6749 // The current broadcast is waiting for this app's receiver
6750 // to be finished. Looks like that's not going to happen, so
6751 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006752 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006753 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6754 r.resultExtras, r.resultAbort, true);
6755 reschedule = true;
6756 }
6757 r = mPendingBroadcast;
6758 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006759 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006760 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006761 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006762 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6763 r.resultExtras, r.resultAbort, true);
6764 reschedule = true;
6765 }
6766 if (reschedule) {
6767 scheduleBroadcastsLocked();
6768 }
6769 }
6770
Dan Egnor60d87622009-12-16 16:32:58 -08006771 /**
6772 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6773 * The application process will exit immediately after this call returns.
6774 * @param app object of the crashing app, null for the system server
6775 * @param crashInfo describing the exception
6776 */
6777 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6778 ProcessRecord r = findAppProcess(app);
6779
6780 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6781 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006782 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006783 crashInfo.exceptionClassName,
6784 crashInfo.exceptionMessage,
6785 crashInfo.throwFileName,
6786 crashInfo.throwLineNumber);
6787
Dan Egnor42471dd2010-01-07 17:25:22 -08006788 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006789
6790 crashApplication(r, crashInfo);
6791 }
6792
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006793 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006794 IBinder app,
6795 int violationMask,
6796 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006797 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006798
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006799 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006800 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006801 boolean logIt = true;
6802 synchronized (mAlreadyLoggedViolatedStacks) {
6803 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6804 logIt = false;
6805 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006806 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006807 // the relative pain numbers, without logging all
6808 // the stack traces repeatedly. We'd want to do
6809 // likewise in the client code, which also does
6810 // dup suppression, before the Binder call.
6811 } else {
6812 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6813 mAlreadyLoggedViolatedStacks.clear();
6814 }
6815 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6816 }
6817 }
6818 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006819 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006820 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006821 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006822
6823 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6824 AppErrorResult result = new AppErrorResult();
6825 synchronized (this) {
6826 final long origId = Binder.clearCallingIdentity();
6827
6828 Message msg = Message.obtain();
6829 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6830 HashMap<String, Object> data = new HashMap<String, Object>();
6831 data.put("result", result);
6832 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006833 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006834 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006835 msg.obj = data;
6836 mHandler.sendMessage(msg);
6837
6838 Binder.restoreCallingIdentity(origId);
6839 }
6840 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006841 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006842 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006843 }
6844
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006845 // Depending on the policy in effect, there could be a bunch of
6846 // these in quick succession so we try to batch these together to
6847 // minimize disk writes, number of dropbox entries, and maximize
6848 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006849 private void logStrictModeViolationToDropBox(
6850 ProcessRecord process,
6851 StrictMode.ViolationInfo info) {
6852 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006853 return;
6854 }
6855 final boolean isSystemApp = process == null ||
6856 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6857 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6858 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6859 final DropBoxManager dbox = (DropBoxManager)
6860 mContext.getSystemService(Context.DROPBOX_SERVICE);
6861
6862 // Exit early if the dropbox isn't configured to accept this report type.
6863 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6864
6865 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006866 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006867 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6868 synchronized (sb) {
6869 bufferWasEmpty = sb.length() == 0;
6870 appendDropBoxProcessHeaders(process, sb);
6871 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6872 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006873 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6874 if (info.violationNumThisLoop != 0) {
6875 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6876 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006877 if (info.numAnimationsRunning != 0) {
6878 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6879 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006880 if (info.broadcastIntentAction != null) {
6881 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6882 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006883 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006884 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006885 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08006886 if (info.numInstances != -1) {
6887 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
6888 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006889 if (info.tags != null) {
6890 for (String tag : info.tags) {
6891 sb.append("Span-Tag: ").append(tag).append("\n");
6892 }
6893 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006894 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006895 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6896 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006897 }
6898 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006899
6900 // Only buffer up to ~64k. Various logging bits truncate
6901 // things at 128k.
6902 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006903 }
6904
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006905 // Flush immediately if the buffer's grown too large, or this
6906 // is a non-system app. Non-system apps are isolated with a
6907 // different tag & policy and not batched.
6908 //
6909 // Batching is useful during internal testing with
6910 // StrictMode settings turned up high. Without batching,
6911 // thousands of separate files could be created on boot.
6912 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006913 new Thread("Error dump: " + dropboxTag) {
6914 @Override
6915 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006916 String report;
6917 synchronized (sb) {
6918 report = sb.toString();
6919 sb.delete(0, sb.length());
6920 sb.trimToSize();
6921 }
6922 if (report.length() != 0) {
6923 dbox.addText(dropboxTag, report);
6924 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006925 }
6926 }.start();
6927 return;
6928 }
6929
6930 // System app batching:
6931 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006932 // An existing dropbox-writing thread is outstanding, so
6933 // we don't need to start it up. The existing thread will
6934 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006935 return;
6936 }
6937
6938 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6939 // (After this point, we shouldn't access AMS internal data structures.)
6940 new Thread("Error dump: " + dropboxTag) {
6941 @Override
6942 public void run() {
6943 // 5 second sleep to let stacks arrive and be batched together
6944 try {
6945 Thread.sleep(5000); // 5 seconds
6946 } catch (InterruptedException e) {}
6947
6948 String errorReport;
6949 synchronized (mStrictModeBuffer) {
6950 errorReport = mStrictModeBuffer.toString();
6951 if (errorReport.length() == 0) {
6952 return;
6953 }
6954 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6955 mStrictModeBuffer.trimToSize();
6956 }
6957 dbox.addText(dropboxTag, errorReport);
6958 }
6959 }.start();
6960 }
6961
Dan Egnor60d87622009-12-16 16:32:58 -08006962 /**
6963 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6964 * @param app object of the crashing app, null for the system server
6965 * @param tag reported by the caller
6966 * @param crashInfo describing the context of the error
6967 * @return true if the process should exit immediately (WTF is fatal)
6968 */
6969 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006970 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006971 ProcessRecord r = findAppProcess(app);
6972
6973 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6974 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006975 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006976 tag, crashInfo.exceptionMessage);
6977
Dan Egnor42471dd2010-01-07 17:25:22 -08006978 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006979
Doug Zongker43866e02010-01-07 12:09:54 -08006980 if (Settings.Secure.getInt(mContext.getContentResolver(),
6981 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006982 crashApplication(r, crashInfo);
6983 return true;
6984 } else {
6985 return false;
6986 }
6987 }
6988
6989 /**
6990 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6991 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6992 */
6993 private ProcessRecord findAppProcess(IBinder app) {
6994 if (app == null) {
6995 return null;
6996 }
6997
6998 synchronized (this) {
6999 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7000 final int NA = apps.size();
7001 for (int ia=0; ia<NA; ia++) {
7002 ProcessRecord p = apps.valueAt(ia);
7003 if (p.thread != null && p.thread.asBinder() == app) {
7004 return p;
7005 }
7006 }
7007 }
7008
Joe Onorato8a9b2202010-02-26 18:56:32 -08007009 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007010 return null;
7011 }
7012 }
7013
7014 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007015 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7016 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007017 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007018 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
7019 // Note: ProcessRecord 'process' is guarded by the service
7020 // instance. (notably process.pkgList, which could otherwise change
7021 // concurrently during execution of this method)
7022 synchronized (this) {
7023 if (process == null || process.pid == MY_PID) {
7024 sb.append("Process: system_server\n");
7025 } else {
7026 sb.append("Process: ").append(process.processName).append("\n");
7027 }
7028 if (process == null) {
7029 return;
7030 }
Dan Egnora455d192010-03-12 08:52:28 -08007031 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007032 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007033 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7034 for (String pkg : process.pkgList) {
7035 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007036 try {
Dan Egnora455d192010-03-12 08:52:28 -08007037 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7038 if (pi != null) {
7039 sb.append(" v").append(pi.versionCode);
7040 if (pi.versionName != null) {
7041 sb.append(" (").append(pi.versionName).append(")");
7042 }
7043 }
7044 } catch (RemoteException e) {
7045 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007046 }
Dan Egnora455d192010-03-12 08:52:28 -08007047 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007048 }
Dan Egnora455d192010-03-12 08:52:28 -08007049 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007050 }
7051
7052 private static String processClass(ProcessRecord process) {
7053 if (process == null || process.pid == MY_PID) {
7054 return "system_server";
7055 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7056 return "system_app";
7057 } else {
7058 return "data_app";
7059 }
7060 }
7061
7062 /**
7063 * Write a description of an error (crash, WTF, ANR) to the drop box.
7064 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7065 * @param process which caused the error, null means the system server
7066 * @param activity which triggered the error, null if unknown
7067 * @param parent activity related to the error, null if unknown
7068 * @param subject line related to the error, null if absent
7069 * @param report in long form describing the error, null if absent
7070 * @param logFile to include in the report, null if none
7071 * @param crashInfo giving an application stack trace, null if absent
7072 */
7073 public void addErrorToDropBox(String eventType,
7074 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7075 final String report, final File logFile,
7076 final ApplicationErrorReport.CrashInfo crashInfo) {
7077 // NOTE -- this must never acquire the ActivityManagerService lock,
7078 // otherwise the watchdog may be prevented from resetting the system.
7079
7080 final String dropboxTag = processClass(process) + "_" + eventType;
7081 final DropBoxManager dbox = (DropBoxManager)
7082 mContext.getSystemService(Context.DROPBOX_SERVICE);
7083
7084 // Exit early if the dropbox isn't configured to accept this report type.
7085 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7086
7087 final StringBuilder sb = new StringBuilder(1024);
7088 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007089 if (activity != null) {
7090 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7091 }
7092 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7093 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7094 }
7095 if (parent != null && parent != activity) {
7096 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7097 }
7098 if (subject != null) {
7099 sb.append("Subject: ").append(subject).append("\n");
7100 }
7101 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007102 if (Debug.isDebuggerConnected()) {
7103 sb.append("Debugger: Connected\n");
7104 }
Dan Egnora455d192010-03-12 08:52:28 -08007105 sb.append("\n");
7106
7107 // Do the rest in a worker thread to avoid blocking the caller on I/O
7108 // (After this point, we shouldn't access AMS internal data structures.)
7109 Thread worker = new Thread("Error dump: " + dropboxTag) {
7110 @Override
7111 public void run() {
7112 if (report != null) {
7113 sb.append(report);
7114 }
7115 if (logFile != null) {
7116 try {
7117 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7118 } catch (IOException e) {
7119 Slog.e(TAG, "Error reading " + logFile, e);
7120 }
7121 }
7122 if (crashInfo != null && crashInfo.stackTrace != null) {
7123 sb.append(crashInfo.stackTrace);
7124 }
7125
7126 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7127 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7128 if (lines > 0) {
7129 sb.append("\n");
7130
7131 // Merge several logcat streams, and take the last N lines
7132 InputStreamReader input = null;
7133 try {
7134 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7135 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7136 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7137
7138 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7139 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7140 input = new InputStreamReader(logcat.getInputStream());
7141
7142 int num;
7143 char[] buf = new char[8192];
7144 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7145 } catch (IOException e) {
7146 Slog.e(TAG, "Error running logcat", e);
7147 } finally {
7148 if (input != null) try { input.close(); } catch (IOException e) {}
7149 }
7150 }
7151
7152 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007153 }
Dan Egnora455d192010-03-12 08:52:28 -08007154 };
7155
7156 if (process == null || process.pid == MY_PID) {
7157 worker.run(); // We may be about to die -- need to run this synchronously
7158 } else {
7159 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007160 }
7161 }
7162
7163 /**
7164 * Bring up the "unexpected error" dialog box for a crashing app.
7165 * Deal with edge cases (intercepts from instrumented applications,
7166 * ActivityController, error intent receivers, that sort of thing).
7167 * @param r the application crashing
7168 * @param crashInfo describing the failure
7169 */
7170 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007171 long timeMillis = System.currentTimeMillis();
7172 String shortMsg = crashInfo.exceptionClassName;
7173 String longMsg = crashInfo.exceptionMessage;
7174 String stackTrace = crashInfo.stackTrace;
7175 if (shortMsg != null && longMsg != null) {
7176 longMsg = shortMsg + ": " + longMsg;
7177 } else if (shortMsg != null) {
7178 longMsg = shortMsg;
7179 }
7180
Dan Egnor60d87622009-12-16 16:32:58 -08007181 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007182 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007183 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007184 try {
7185 String name = r != null ? r.processName : null;
7186 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007187 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007188 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007189 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007190 + " at watcher's request");
7191 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007192 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007193 }
7194 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007195 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007196 }
7197 }
7198
7199 final long origId = Binder.clearCallingIdentity();
7200
7201 // If this process is running instrumentation, finish it.
7202 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007203 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007204 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007205 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7206 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007207 Bundle info = new Bundle();
7208 info.putString("shortMsg", shortMsg);
7209 info.putString("longMsg", longMsg);
7210 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7211 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007212 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007213 }
7214
Dan Egnor60d87622009-12-16 16:32:58 -08007215 // If we can't identify the process or it's already exceeded its crash quota,
7216 // quit right away without showing a crash dialog.
7217 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007218 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007219 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007220 }
7221
7222 Message msg = Message.obtain();
7223 msg.what = SHOW_ERROR_MSG;
7224 HashMap data = new HashMap();
7225 data.put("result", result);
7226 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007227 msg.obj = data;
7228 mHandler.sendMessage(msg);
7229
7230 Binder.restoreCallingIdentity(origId);
7231 }
7232
7233 int res = result.get();
7234
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007235 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007236 synchronized (this) {
7237 if (r != null) {
7238 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7239 SystemClock.uptimeMillis());
7240 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007241 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007242 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007243 }
7244 }
7245
7246 if (appErrorIntent != null) {
7247 try {
7248 mContext.startActivity(appErrorIntent);
7249 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007250 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007253 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007254
7255 Intent createAppErrorIntentLocked(ProcessRecord r,
7256 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7257 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007258 if (report == null) {
7259 return null;
7260 }
7261 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7262 result.setComponent(r.errorReportReceiver);
7263 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7264 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7265 return result;
7266 }
7267
Dan Egnorb7f03672009-12-09 16:22:32 -08007268 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7269 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007270 if (r.errorReportReceiver == null) {
7271 return null;
7272 }
7273
7274 if (!r.crashing && !r.notResponding) {
7275 return null;
7276 }
7277
Dan Egnorb7f03672009-12-09 16:22:32 -08007278 ApplicationErrorReport report = new ApplicationErrorReport();
7279 report.packageName = r.info.packageName;
7280 report.installerPackageName = r.errorReportReceiver.getPackageName();
7281 report.processName = r.processName;
7282 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007283 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007284
Dan Egnorb7f03672009-12-09 16:22:32 -08007285 if (r.crashing) {
7286 report.type = ApplicationErrorReport.TYPE_CRASH;
7287 report.crashInfo = crashInfo;
7288 } else if (r.notResponding) {
7289 report.type = ApplicationErrorReport.TYPE_ANR;
7290 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007291
Dan Egnorb7f03672009-12-09 16:22:32 -08007292 report.anrInfo.activity = r.notRespondingReport.tag;
7293 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7294 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007295 }
7296
Dan Egnorb7f03672009-12-09 16:22:32 -08007297 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007298 }
7299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007300 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7301 // assume our apps are happy - lazy create the list
7302 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7303
7304 synchronized (this) {
7305
7306 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007307 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7308 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007309 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7310 // This one's in trouble, so we'll generate a report for it
7311 // crashes are higher priority (in case there's a crash *and* an anr)
7312 ActivityManager.ProcessErrorStateInfo report = null;
7313 if (app.crashing) {
7314 report = app.crashingReport;
7315 } else if (app.notResponding) {
7316 report = app.notRespondingReport;
7317 }
7318
7319 if (report != null) {
7320 if (errList == null) {
7321 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7322 }
7323 errList.add(report);
7324 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007325 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007326 " crashing = " + app.crashing +
7327 " notResponding = " + app.notResponding);
7328 }
7329 }
7330 }
7331 }
7332
7333 return errList;
7334 }
7335
7336 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7337 // Lazy instantiation of list
7338 List<ActivityManager.RunningAppProcessInfo> runList = null;
7339 synchronized (this) {
7340 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007341 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7342 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007343 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7344 // Generate process state info for running application
7345 ActivityManager.RunningAppProcessInfo currApp =
7346 new ActivityManager.RunningAppProcessInfo(app.processName,
7347 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007348 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007349 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007350 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007351 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007352 if (app.persistent) {
7353 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7354 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007355 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007356 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007357 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7358 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7359 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007360 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7361 } else if (adj >= HOME_APP_ADJ) {
7362 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7363 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007364 } else if (adj >= SECONDARY_SERVER_ADJ) {
7365 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007366 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007367 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007368 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7369 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007370 } else if (adj >= VISIBLE_APP_ADJ) {
7371 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7372 } else {
7373 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7374 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007375 currApp.importanceReasonCode = app.adjTypeCode;
7376 if (app.adjSource instanceof ProcessRecord) {
7377 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007378 } else if (app.adjSource instanceof ActivityRecord) {
7379 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007380 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7381 }
7382 if (app.adjTarget instanceof ComponentName) {
7383 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7384 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007385 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007386 // + " lru=" + currApp.lru);
7387 if (runList == null) {
7388 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7389 }
7390 runList.add(currApp);
7391 }
7392 }
7393 }
7394 return runList;
7395 }
7396
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007397 public List<ApplicationInfo> getRunningExternalApplications() {
7398 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7399 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7400 if (runningApps != null && runningApps.size() > 0) {
7401 Set<String> extList = new HashSet<String>();
7402 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7403 if (app.pkgList != null) {
7404 for (String pkg : app.pkgList) {
7405 extList.add(pkg);
7406 }
7407 }
7408 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007409 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007410 for (String pkg : extList) {
7411 try {
7412 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7413 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7414 retList.add(info);
7415 }
7416 } catch (RemoteException e) {
7417 }
7418 }
7419 }
7420 return retList;
7421 }
7422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 @Override
7424 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007425 if (checkCallingPermission(android.Manifest.permission.DUMP)
7426 != PackageManager.PERMISSION_GRANTED) {
7427 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7428 + Binder.getCallingPid()
7429 + ", uid=" + Binder.getCallingUid()
7430 + " without permission "
7431 + android.Manifest.permission.DUMP);
7432 return;
7433 }
7434
7435 boolean dumpAll = false;
7436
7437 int opti = 0;
7438 while (opti < args.length) {
7439 String opt = args[opti];
7440 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7441 break;
7442 }
7443 opti++;
7444 if ("-a".equals(opt)) {
7445 dumpAll = true;
7446 } else if ("-h".equals(opt)) {
7447 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007448 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007449 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007450 pw.println(" a[ctivities]: activity stack state");
7451 pw.println(" b[roadcasts]: broadcast state");
7452 pw.println(" i[ntents]: pending intent state");
7453 pw.println(" p[rocesses]: process state");
7454 pw.println(" o[om]: out of memory management");
7455 pw.println(" prov[iders]: content provider state");
7456 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007457 pw.println(" service [name]: service client-side state");
Dianne Hackborn30d71892010-12-11 10:37:55 -08007458 pw.println(" cmd may also be a component name (com.foo/.myApp),");
7459 pw.println(" a partial substring in a component name, or an");
7460 pw.println(" ActivityRecord hex object identifier.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007462 } else {
7463 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007464 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007465 }
7466
7467 // Is the caller requesting to dump a particular piece of data?
7468 if (opti < args.length) {
7469 String cmd = args[opti];
7470 opti++;
7471 if ("activities".equals(cmd) || "a".equals(cmd)) {
7472 synchronized (this) {
7473 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007474 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007475 return;
7476 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7477 synchronized (this) {
7478 dumpBroadcastsLocked(fd, pw, args, opti, true);
7479 }
7480 return;
7481 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7482 synchronized (this) {
7483 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7484 }
7485 return;
7486 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7487 synchronized (this) {
7488 dumpProcessesLocked(fd, pw, args, opti, true);
7489 }
7490 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007491 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7492 synchronized (this) {
7493 dumpOomLocked(fd, pw, args, opti, true);
7494 }
7495 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007496 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7497 synchronized (this) {
7498 dumpProvidersLocked(fd, pw, args, opti, true);
7499 }
7500 return;
7501 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007502 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007503 return;
7504 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7505 synchronized (this) {
7506 dumpServicesLocked(fd, pw, args, opti, true);
7507 }
7508 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007509 } else {
7510 // Dumping a single activity?
7511 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7512 return;
7513 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007514 pw.println("Bad activity command, or no activities match: " + cmd);
7515 pw.println("Use -h for help.");
7516 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007517 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007518 }
7519
7520 // No piece of data specified, dump everything.
7521 synchronized (this) {
7522 boolean needSep;
7523 if (dumpAll) {
7524 pw.println("Providers in Current Activity Manager State:");
7525 }
7526 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7527 if (needSep) {
7528 pw.println(" ");
7529 }
7530 if (dumpAll) {
7531 pw.println("-------------------------------------------------------------------------------");
7532 pw.println("Broadcasts in Current Activity Manager State:");
7533 }
7534 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7535 if (needSep) {
7536 pw.println(" ");
7537 }
7538 if (dumpAll) {
7539 pw.println("-------------------------------------------------------------------------------");
7540 pw.println("Services in Current Activity Manager State:");
7541 }
7542 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7543 if (needSep) {
7544 pw.println(" ");
7545 }
7546 if (dumpAll) {
7547 pw.println("-------------------------------------------------------------------------------");
7548 pw.println("PendingIntents in Current Activity Manager State:");
7549 }
7550 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7551 if (needSep) {
7552 pw.println(" ");
7553 }
7554 if (dumpAll) {
7555 pw.println("-------------------------------------------------------------------------------");
7556 pw.println("Activities in Current Activity Manager State:");
7557 }
7558 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7559 if (needSep) {
7560 pw.println(" ");
7561 }
7562 if (dumpAll) {
7563 pw.println("-------------------------------------------------------------------------------");
7564 pw.println("Processes in Current Activity Manager State:");
7565 }
7566 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7567 }
7568 }
7569
7570 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7571 int opti, boolean dumpAll, boolean needHeader) {
7572 if (needHeader) {
7573 pw.println(" Activity stack:");
7574 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007575 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007576 pw.println(" ");
7577 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007578 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7579 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007581 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007582 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007583 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007584 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007585 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007586 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007587 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007588 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007589 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7590 pw.println(" ");
7591 pw.println(" Activities waiting to sleep:");
7592 dumpHistoryList(pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false);
7593 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007594 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007595 pw.println(" ");
7596 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007597 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007600 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007601 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7602 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007603 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007604 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007605 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007607 if (dumpAll && mRecentTasks.size() > 0) {
7608 pw.println(" ");
7609 pw.println("Recent tasks in Current Activity Manager State:");
7610
7611 final int N = mRecentTasks.size();
7612 for (int i=0; i<N; i++) {
7613 TaskRecord tr = mRecentTasks.get(i);
7614 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7615 pw.println(tr);
7616 mRecentTasks.get(i).dump(pw, " ");
7617 }
7618 }
7619
7620 pw.println(" ");
7621 pw.println(" mCurTask: " + mCurTask);
7622
7623 return true;
7624 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007625
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007626 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7627 int opti, boolean dumpAll) {
7628 boolean needSep = false;
7629 int numPers = 0;
7630
7631 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007632 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7633 final int NA = procs.size();
7634 for (int ia=0; ia<NA; ia++) {
7635 if (!needSep) {
7636 pw.println(" All known processes:");
7637 needSep = true;
7638 }
7639 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007640 pw.print(r.persistent ? " *PERS*" : " *APP*");
7641 pw.print(" UID "); pw.print(procs.keyAt(ia));
7642 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007643 r.dump(pw, " ");
7644 if (r.persistent) {
7645 numPers++;
7646 }
7647 }
7648 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007649 }
7650
7651 if (mLruProcesses.size() > 0) {
7652 if (needSep) pw.println(" ");
7653 needSep = true;
7654 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007655 dumpProcessOomList(pw, this, mLruProcesses, " ",
7656 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007657 needSep = true;
7658 }
7659
7660 synchronized (mPidsSelfLocked) {
7661 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007662 if (needSep) pw.println(" ");
7663 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007664 pw.println(" PID mappings:");
7665 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7666 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7667 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007668 }
7669 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007670 }
7671
7672 if (mForegroundProcesses.size() > 0) {
7673 if (needSep) pw.println(" ");
7674 needSep = true;
7675 pw.println(" Foreground Processes:");
7676 for (int i=0; i<mForegroundProcesses.size(); i++) {
7677 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7678 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007679 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007680 }
7681
7682 if (mPersistentStartingProcesses.size() > 0) {
7683 if (needSep) pw.println(" ");
7684 needSep = true;
7685 pw.println(" Persisent processes that are starting:");
7686 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007687 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007688 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007689
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007690 if (mStartingProcesses.size() > 0) {
7691 if (needSep) pw.println(" ");
7692 needSep = true;
7693 pw.println(" Processes that are starting:");
7694 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007695 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007698 if (mRemovedProcesses.size() > 0) {
7699 if (needSep) pw.println(" ");
7700 needSep = true;
7701 pw.println(" Processes that are being removed:");
7702 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007703 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007704 }
7705
7706 if (mProcessesOnHold.size() > 0) {
7707 if (needSep) pw.println(" ");
7708 needSep = true;
7709 pw.println(" Processes that are on old until the system is ready:");
7710 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007711 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007713
Dianne Hackborn287952c2010-09-22 22:34:31 -07007714 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007715
7716 if (mProcessCrashTimes.getMap().size() > 0) {
7717 if (needSep) pw.println(" ");
7718 needSep = true;
7719 pw.println(" Time since processes crashed:");
7720 long now = SystemClock.uptimeMillis();
7721 for (Map.Entry<String, SparseArray<Long>> procs
7722 : mProcessCrashTimes.getMap().entrySet()) {
7723 SparseArray<Long> uids = procs.getValue();
7724 final int N = uids.size();
7725 for (int i=0; i<N; i++) {
7726 pw.print(" Process "); pw.print(procs.getKey());
7727 pw.print(" uid "); pw.print(uids.keyAt(i));
7728 pw.print(": last crashed ");
7729 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007730 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007731 }
7732 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007734
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007735 if (mBadProcesses.getMap().size() > 0) {
7736 if (needSep) pw.println(" ");
7737 needSep = true;
7738 pw.println(" Bad processes:");
7739 for (Map.Entry<String, SparseArray<Long>> procs
7740 : mBadProcesses.getMap().entrySet()) {
7741 SparseArray<Long> uids = procs.getValue();
7742 final int N = uids.size();
7743 for (int i=0; i<N; i++) {
7744 pw.print(" Bad process "); pw.print(procs.getKey());
7745 pw.print(" uid "); pw.print(uids.keyAt(i));
7746 pw.print(": crashed at time ");
7747 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007748 }
7749 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007752 pw.println(" ");
7753 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007754 if (mHeavyWeightProcess != null) {
7755 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7756 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007757 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007758 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007759 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7760 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7761 || mOrigWaitForDebugger) {
7762 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7763 + " mDebugTransient=" + mDebugTransient
7764 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7765 }
7766 if (mAlwaysFinishActivities || mController != null) {
7767 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7768 + " mController=" + mController);
7769 }
7770 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007772 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007773 + " mProcessesReady=" + mProcessesReady
7774 + " mSystemReady=" + mSystemReady);
7775 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007776 + " mBooted=" + mBooted
7777 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007778 pw.print(" mLastPowerCheckRealtime=");
7779 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7780 pw.println("");
7781 pw.print(" mLastPowerCheckUptime=");
7782 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7783 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007784 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7785 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007786 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007787 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007788
7789 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007790 }
7791
Dianne Hackborn287952c2010-09-22 22:34:31 -07007792 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7793 int opti, boolean needSep, boolean dumpAll) {
7794 if (mProcessesToGc.size() > 0) {
7795 if (needSep) pw.println(" ");
7796 needSep = true;
7797 pw.println(" Processes that are waiting to GC:");
7798 long now = SystemClock.uptimeMillis();
7799 for (int i=0; i<mProcessesToGc.size(); i++) {
7800 ProcessRecord proc = mProcessesToGc.get(i);
7801 pw.print(" Process "); pw.println(proc);
7802 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7803 pw.print(", last gced=");
7804 pw.print(now-proc.lastRequestedGc);
7805 pw.print(" ms ago, last lowMem=");
7806 pw.print(now-proc.lastLowMemory);
7807 pw.println(" ms ago");
7808
7809 }
7810 }
7811 return needSep;
7812 }
7813
7814 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7815 int opti, boolean dumpAll) {
7816 boolean needSep = false;
7817
7818 if (mLruProcesses.size() > 0) {
7819 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7820
7821 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7822 @Override
7823 public int compare(ProcessRecord object1, ProcessRecord object2) {
7824 if (object1.setAdj != object2.setAdj) {
7825 return object1.setAdj > object2.setAdj ? -1 : 1;
7826 }
7827 if (object1.setSchedGroup != object2.setSchedGroup) {
7828 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7829 }
7830 if (object1.keeping != object2.keeping) {
7831 return object1.keeping ? -1 : 1;
7832 }
7833 if (object1.pid != object2.pid) {
7834 return object1.pid > object2.pid ? -1 : 1;
7835 }
7836 return 0;
7837 }
7838 };
7839
7840 Collections.sort(procs, comparator);
7841
7842 if (needSep) pw.println(" ");
7843 needSep = true;
7844 pw.println(" Process OOM control:");
7845 dumpProcessOomList(pw, this, procs, " ",
7846 "Proc", "PERS", true);
7847 needSep = true;
7848 }
7849
7850 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7851
7852 pw.println(" ");
7853 pw.println(" mHomeProcess: " + mHomeProcess);
7854 if (mHeavyWeightProcess != null) {
7855 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7856 }
7857
7858 return true;
7859 }
7860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007861 /**
7862 * There are three ways to call this:
7863 * - no service specified: dump all the services
7864 * - a flattened component name that matched an existing service was specified as the
7865 * first arg: dump that one service
7866 * - the first arg isn't the flattened component name of an existing service:
7867 * dump all services whose component contains the first arg as a substring
7868 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007869 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007870 String[] newArgs;
7871 String componentNameString;
7872 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007873 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007874 componentNameString = null;
7875 newArgs = EMPTY_STRING_ARRAY;
7876 r = null;
7877 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007878 componentNameString = args[opti];
7879 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007881 synchronized (this) {
7882 r = componentName != null ? mServices.get(componentName) : null;
7883 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007884 newArgs = new String[args.length - opti];
7885 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007886 }
7887
7888 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007889 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007891 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7892 synchronized (this) {
7893 for (ServiceRecord r1 : mServices.values()) {
7894 if (componentNameString == null
7895 || r1.name.flattenToString().contains(componentNameString)) {
7896 services.add(r1);
7897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007898 }
7899 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007900 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007901 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007903 }
7904 }
7905
7906 /**
7907 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7908 * there is a thread associated with the service.
7909 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007910 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7911 pw.println("------------------------------------------------------------"
7912 + "-------------------");
7913 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007914 if (r.app != null && r.app.thread != null) {
7915 try {
7916 // flush anything that is already in the PrintWriter since the thread is going
7917 // to write to the file descriptor directly
7918 pw.flush();
7919 r.app.thread.dumpService(fd, r, args);
7920 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007921 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007922 } catch (RemoteException e) {
7923 pw.println("got a RemoteException while dumping the service");
7924 }
7925 }
7926 }
7927
Dianne Hackborn625ac272010-09-17 18:29:22 -07007928 /**
7929 * There are three things that cmd can be:
7930 * - a flattened component name that matched an existing activity
7931 * - the cmd arg isn't the flattened component name of an existing activity:
7932 * dump all activity whose component contains the cmd as a substring
7933 * - A hex number of the ActivityRecord object instance.
7934 */
7935 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7936 int opti, boolean dumpAll) {
7937 String[] newArgs;
7938 ComponentName componentName = ComponentName.unflattenFromString(name);
7939 int objectId = 0;
Dianne Hackborn30d71892010-12-11 10:37:55 -08007940 if (componentName == null) {
7941 // Not a '/' separated full component name; maybe an object ID?
7942 try {
7943 objectId = Integer.parseInt(name, 16);
7944 name = null;
7945 componentName = null;
7946 } catch (RuntimeException e) {
7947 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007948 }
7949 newArgs = new String[args.length - opti];
7950 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7951
7952 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7953 synchronized (this) {
7954 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7955 if (componentName != null) {
7956 if (r1.intent.getComponent().equals(componentName)) {
7957 activities.add(r1);
7958 }
7959 } else if (name != null) {
7960 if (r1.intent.getComponent().flattenToString().contains(name)) {
7961 activities.add(r1);
7962 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007963 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07007964 activities.add(r1);
7965 }
7966 }
7967 }
7968
7969 if (activities.size() <= 0) {
7970 return false;
7971 }
7972
Dianne Hackborn30d71892010-12-11 10:37:55 -08007973 TaskRecord lastTask = null;
7974 for (int i=activities.size()-1; i>=0; i--) {
7975 ActivityRecord r = (ActivityRecord)activities.get(i);
7976 if (lastTask != r.task) {
7977 lastTask = r.task;
7978 pw.print("* Task "); pw.print(lastTask.affinity);
7979 pw.print(" id="); pw.println(lastTask.taskId);
7980 if (dumpAll) {
7981 lastTask.dump(pw, " ");
7982 }
7983 }
7984 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007985 }
7986 return true;
7987 }
7988
7989 /**
7990 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7991 * there is a thread associated with the activity.
7992 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08007993 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
7994 ActivityRecord r, String[] args, boolean dumpAll) {
7995 synchronized (this) {
7996 pw.print(prefix); pw.print("* Activity ");
7997 pw.print(Integer.toHexString(System.identityHashCode(r)));
7998 pw.print(" "); pw.print(r.shortComponentName); pw.print(" pid=");
7999 if (r.app != null) pw.println(r.app.pid);
8000 else pw.println("(not running)");
8001 if (dumpAll) {
8002 r.dump(pw, prefix + " ");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008003 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008004 }
8005 if (r.app != null && r.app.thread != null) {
8006 try {
8007 // flush anything that is already in the PrintWriter since the thread is going
8008 // to write to the file descriptor directly
8009 pw.flush();
Dianne Hackborn30d71892010-12-11 10:37:55 -08008010 r.app.thread.dumpActivity(fd, r, prefix + " ", args);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008011 pw.flush();
8012 } catch (RemoteException e) {
8013 pw.println("got a RemoteException while dumping the activity");
8014 }
8015 }
8016 }
8017
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008018 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8019 int opti, boolean dumpAll) {
8020 boolean needSep = false;
8021
8022 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008023 if (mRegisteredReceivers.size() > 0) {
8024 pw.println(" ");
8025 pw.println(" Registered Receivers:");
8026 Iterator it = mRegisteredReceivers.values().iterator();
8027 while (it.hasNext()) {
8028 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008029 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008030 r.dump(pw, " ");
8031 }
8032 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008034 pw.println(" ");
8035 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008036 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008037 needSep = true;
8038 }
8039
8040 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8041 || mPendingBroadcast != null) {
8042 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008043 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008044 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008046 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8047 pw.println(" Broadcast #" + i + ":");
8048 mParallelBroadcasts.get(i).dump(pw, " ");
8049 }
8050 if (mOrderedBroadcasts.size() > 0) {
8051 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008052 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008053 }
8054 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8055 pw.println(" Serialized Broadcast #" + i + ":");
8056 mOrderedBroadcasts.get(i).dump(pw, " ");
8057 }
8058 pw.println(" ");
8059 pw.println(" Pending broadcast:");
8060 if (mPendingBroadcast != null) {
8061 mPendingBroadcast.dump(pw, " ");
8062 } else {
8063 pw.println(" (null)");
8064 }
8065 needSep = true;
8066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008067
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008068 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008070 pw.println(" Historical broadcasts:");
8071 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8072 BroadcastRecord r = mBroadcastHistory[i];
8073 if (r == null) {
8074 break;
8075 }
8076 pw.println(" Historical Broadcast #" + i + ":");
8077 r.dump(pw, " ");
8078 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008079 needSep = true;
8080 }
8081
8082 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08008083 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008084 pw.println(" Sticky broadcasts:");
8085 StringBuilder sb = new StringBuilder(128);
8086 for (Map.Entry<String, ArrayList<Intent>> ent
8087 : mStickyBroadcasts.entrySet()) {
8088 pw.print(" * Sticky action "); pw.print(ent.getKey());
8089 pw.println(":");
8090 ArrayList<Intent> intents = ent.getValue();
8091 final int N = intents.size();
8092 for (int i=0; i<N; i++) {
8093 sb.setLength(0);
8094 sb.append(" Intent: ");
8095 intents.get(i).toShortString(sb, true, false);
8096 pw.println(sb.toString());
8097 Bundle bundle = intents.get(i).getExtras();
8098 if (bundle != null) {
8099 pw.print(" ");
8100 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008101 }
8102 }
8103 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008104 needSep = true;
8105 }
8106
8107 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008108 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008109 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008110 pw.println(" mHandler:");
8111 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008112 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008113 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008114
8115 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008116 }
8117
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008118 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8119 int opti, boolean dumpAll) {
8120 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008121
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008122 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 if (mServices.size() > 0) {
8124 pw.println(" Active services:");
8125 Iterator<ServiceRecord> it = mServices.values().iterator();
8126 while (it.hasNext()) {
8127 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008128 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008129 r.dump(pw, " ");
8130 }
8131 needSep = true;
8132 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008133 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008134
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008135 if (mPendingServices.size() > 0) {
8136 if (needSep) pw.println(" ");
8137 pw.println(" Pending services:");
8138 for (int i=0; i<mPendingServices.size(); i++) {
8139 ServiceRecord r = mPendingServices.get(i);
8140 pw.print(" * Pending "); pw.println(r);
8141 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008142 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008143 needSep = true;
8144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008145
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008146 if (mRestartingServices.size() > 0) {
8147 if (needSep) pw.println(" ");
8148 pw.println(" Restarting services:");
8149 for (int i=0; i<mRestartingServices.size(); i++) {
8150 ServiceRecord r = mRestartingServices.get(i);
8151 pw.print(" * Restarting "); pw.println(r);
8152 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008153 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008154 needSep = true;
8155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008156
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008157 if (mStoppingServices.size() > 0) {
8158 if (needSep) pw.println(" ");
8159 pw.println(" Stopping services:");
8160 for (int i=0; i<mStoppingServices.size(); i++) {
8161 ServiceRecord r = mStoppingServices.get(i);
8162 pw.print(" * Stopping "); pw.println(r);
8163 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008164 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008165 needSep = true;
8166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008167
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008168 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008169 if (mServiceConnections.size() > 0) {
8170 if (needSep) pw.println(" ");
8171 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008172 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 = mServiceConnections.values().iterator();
8174 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008175 ArrayList<ConnectionRecord> r = it.next();
8176 for (int i=0; i<r.size(); i++) {
8177 pw.print(" * "); pw.println(r.get(i));
8178 r.get(i).dump(pw, " ");
8179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008180 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008181 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008182 }
8183 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008184
8185 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008186 }
8187
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008188 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8189 int opti, boolean dumpAll) {
8190 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008191
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008192 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008193 if (mProvidersByClass.size() > 0) {
8194 if (needSep) pw.println(" ");
8195 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008196 Iterator<Map.Entry<String, ContentProviderRecord>> it
8197 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008198 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008199 Map.Entry<String, ContentProviderRecord> e = it.next();
8200 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008201 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008202 r.dump(pw, " ");
8203 }
8204 needSep = true;
8205 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008206
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008207 if (mProvidersByName.size() > 0) {
8208 pw.println(" ");
8209 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008210 Iterator<Map.Entry<String, ContentProviderRecord>> it
8211 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008212 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008213 Map.Entry<String, ContentProviderRecord> e = it.next();
8214 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008215 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8216 pw.println(r);
8217 }
8218 needSep = true;
8219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008220 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008221
8222 if (mLaunchingProviders.size() > 0) {
8223 if (needSep) pw.println(" ");
8224 pw.println(" Launching content providers:");
8225 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8226 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8227 pw.println(mLaunchingProviders.get(i));
8228 }
8229 needSep = true;
8230 }
8231
8232 if (mGrantedUriPermissions.size() > 0) {
8233 pw.println();
8234 pw.println("Granted Uri Permissions:");
8235 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8236 int uid = mGrantedUriPermissions.keyAt(i);
8237 HashMap<Uri, UriPermission> perms
8238 = mGrantedUriPermissions.valueAt(i);
8239 pw.print(" * UID "); pw.print(uid);
8240 pw.println(" holds:");
8241 for (UriPermission perm : perms.values()) {
8242 pw.print(" "); pw.println(perm);
8243 perm.dump(pw, " ");
8244 }
8245 }
8246 needSep = true;
8247 }
8248
8249 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008250 }
8251
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008252 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8253 int opti, boolean dumpAll) {
8254 boolean needSep = false;
8255
8256 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008257 if (this.mIntentSenderRecords.size() > 0) {
8258 Iterator<WeakReference<PendingIntentRecord>> it
8259 = mIntentSenderRecords.values().iterator();
8260 while (it.hasNext()) {
8261 WeakReference<PendingIntentRecord> ref = it.next();
8262 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008263 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008264 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008265 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 rec.dump(pw, " ");
8267 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008268 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008269 }
8270 }
8271 }
8272 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008273
8274 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008275 }
8276
8277 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008278 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008279 TaskRecord lastTask = null;
8280 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008281 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008282 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008283 if (lastTask != r.task) {
8284 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008285 pw.print(prefix);
8286 pw.print(full ? "* " : " ");
8287 pw.println(lastTask);
8288 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008289 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008291 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008292 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8293 pw.print(" #"); pw.print(i); pw.print(": ");
8294 pw.println(r);
8295 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008296 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008297 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008298 }
8299 }
8300
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008301 private static String buildOomTag(String prefix, String space, int val, int base) {
8302 if (val == base) {
8303 if (space == null) return prefix;
8304 return prefix + " ";
8305 }
8306 return prefix + "+" + Integer.toString(val-base);
8307 }
8308
8309 private static final int dumpProcessList(PrintWriter pw,
8310 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008311 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008312 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008313 final int N = list.size()-1;
8314 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008315 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008316 pw.println(String.format("%s%s #%2d: %s",
8317 prefix, (r.persistent ? persistentLabel : normalLabel),
8318 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008319 if (r.persistent) {
8320 numPers++;
8321 }
8322 }
8323 return numPers;
8324 }
8325
Dianne Hackborn287952c2010-09-22 22:34:31 -07008326 private static final void dumpProcessOomList(PrintWriter pw,
8327 ActivityManagerService service, List<ProcessRecord> list,
8328 String prefix, String normalLabel, String persistentLabel,
8329 boolean inclDetails) {
8330
8331 final long curRealtime = SystemClock.elapsedRealtime();
8332 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8333 final long curUptime = SystemClock.uptimeMillis();
8334 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8335
8336 final int N = list.size()-1;
8337 for (int i=N; i>=0; i--) {
8338 ProcessRecord r = list.get(i);
8339 String oomAdj;
8340 if (r.setAdj >= EMPTY_APP_ADJ) {
8341 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8342 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8343 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8344 } else if (r.setAdj >= HOME_APP_ADJ) {
8345 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8346 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8347 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8348 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8349 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8350 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8351 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8352 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8353 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8354 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8355 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8356 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8357 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8358 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8359 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8360 } else if (r.setAdj >= SYSTEM_ADJ) {
8361 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8362 } else {
8363 oomAdj = Integer.toString(r.setAdj);
8364 }
8365 String schedGroup;
8366 switch (r.setSchedGroup) {
8367 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8368 schedGroup = "B";
8369 break;
8370 case Process.THREAD_GROUP_DEFAULT:
8371 schedGroup = "F";
8372 break;
8373 default:
8374 schedGroup = Integer.toString(r.setSchedGroup);
8375 break;
8376 }
8377 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8378 prefix, (r.persistent ? persistentLabel : normalLabel),
8379 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8380 if (r.adjSource != null || r.adjTarget != null) {
8381 pw.print(prefix);
8382 pw.print(" ");
8383 if (r.adjTarget instanceof ComponentName) {
8384 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8385 } else if (r.adjTarget != null) {
8386 pw.print(r.adjTarget.toString());
8387 } else {
8388 pw.print("{null}");
8389 }
8390 pw.print("<=");
8391 if (r.adjSource instanceof ProcessRecord) {
8392 pw.print("Proc{");
8393 pw.print(((ProcessRecord)r.adjSource).toShortString());
8394 pw.println("}");
8395 } else if (r.adjSource != null) {
8396 pw.println(r.adjSource.toString());
8397 } else {
8398 pw.println("{null}");
8399 }
8400 }
8401 if (inclDetails) {
8402 pw.print(prefix);
8403 pw.print(" ");
8404 pw.print("oom: max="); pw.print(r.maxAdj);
8405 pw.print(" hidden="); pw.print(r.hiddenAdj);
8406 pw.print(" curRaw="); pw.print(r.curRawAdj);
8407 pw.print(" setRaw="); pw.print(r.setRawAdj);
8408 pw.print(" cur="); pw.print(r.curAdj);
8409 pw.print(" set="); pw.println(r.setAdj);
8410 pw.print(prefix);
8411 pw.print(" ");
8412 pw.print("keeping="); pw.print(r.keeping);
8413 pw.print(" hidden="); pw.print(r.hidden);
8414 pw.print(" empty="); pw.println(r.empty);
8415
8416 if (!r.keeping) {
8417 if (r.lastWakeTime != 0) {
8418 long wtime;
8419 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8420 synchronized (stats) {
8421 wtime = stats.getProcessWakeTime(r.info.uid,
8422 r.pid, curRealtime);
8423 }
8424 long timeUsed = wtime - r.lastWakeTime;
8425 pw.print(prefix);
8426 pw.print(" ");
8427 pw.print("keep awake over ");
8428 TimeUtils.formatDuration(realtimeSince, pw);
8429 pw.print(" used ");
8430 TimeUtils.formatDuration(timeUsed, pw);
8431 pw.print(" (");
8432 pw.print((timeUsed*100)/realtimeSince);
8433 pw.println("%)");
8434 }
8435 if (r.lastCpuTime != 0) {
8436 long timeUsed = r.curCpuTime - r.lastCpuTime;
8437 pw.print(prefix);
8438 pw.print(" ");
8439 pw.print("run cpu over ");
8440 TimeUtils.formatDuration(uptimeSince, pw);
8441 pw.print(" used ");
8442 TimeUtils.formatDuration(timeUsed, pw);
8443 pw.print(" (");
8444 pw.print((timeUsed*100)/uptimeSince);
8445 pw.println("%)");
8446 }
8447 }
8448 }
8449 }
8450 }
8451
Dianne Hackborn472ad872010-04-07 17:31:48 -07008452 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008453 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008454 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008455 long uptime = SystemClock.uptimeMillis();
8456 long realtime = SystemClock.elapsedRealtime();
8457
8458 if (isCheckinRequest) {
8459 // short checkin version
8460 pw.println(uptime + "," + realtime);
8461 pw.flush();
8462 } else {
8463 pw.println("Applications Memory Usage (kB):");
8464 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8465 }
8466 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8467 ProcessRecord r = (ProcessRecord)list.get(i);
8468 if (r.thread != null) {
8469 if (!isCheckinRequest) {
8470 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8471 pw.flush();
8472 }
8473 try {
8474 r.thread.asBinder().dump(fd, args);
8475 } catch (RemoteException e) {
8476 if (!isCheckinRequest) {
8477 pw.println("Got RemoteException!");
8478 pw.flush();
8479 }
8480 }
8481 }
8482 }
8483 }
8484
8485 /**
8486 * Searches array of arguments for the specified string
8487 * @param args array of argument strings
8488 * @param value value to search for
8489 * @return true if the value is contained in the array
8490 */
8491 private static boolean scanArgs(String[] args, String value) {
8492 if (args != null) {
8493 for (String arg : args) {
8494 if (value.equals(arg)) {
8495 return true;
8496 }
8497 }
8498 }
8499 return false;
8500 }
8501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502 private final void killServicesLocked(ProcessRecord app,
8503 boolean allowRestart) {
8504 // Report disconnected services.
8505 if (false) {
8506 // XXX we are letting the client link to the service for
8507 // death notifications.
8508 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008509 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008510 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008511 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008512 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008513 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008514 = r.connections.values().iterator();
8515 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008516 ArrayList<ConnectionRecord> cl = jt.next();
8517 for (int i=0; i<cl.size(); i++) {
8518 ConnectionRecord c = cl.get(i);
8519 if (c.binding.client != app) {
8520 try {
8521 //c.conn.connected(r.className, null);
8522 } catch (Exception e) {
8523 // todo: this should be asynchronous!
8524 Slog.w(TAG, "Exception thrown disconnected servce "
8525 + r.shortName
8526 + " from app " + app.processName, e);
8527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 }
8529 }
8530 }
8531 }
8532 }
8533 }
8534 }
8535
8536 // Clean up any connections this application has to other services.
8537 if (app.connections.size() > 0) {
8538 Iterator<ConnectionRecord> it = app.connections.iterator();
8539 while (it.hasNext()) {
8540 ConnectionRecord r = it.next();
8541 removeConnectionLocked(r, app, null);
8542 }
8543 }
8544 app.connections.clear();
8545
8546 if (app.services.size() != 0) {
8547 // Any services running in the application need to be placed
8548 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008549 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008550 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008551 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008552 synchronized (sr.stats.getBatteryStats()) {
8553 sr.stats.stopLaunchedLocked();
8554 }
8555 sr.app = null;
8556 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008557 if (mStoppingServices.remove(sr)) {
8558 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8559 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008560
8561 boolean hasClients = sr.bindings.size() > 0;
8562 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008563 Iterator<IntentBindRecord> bindings
8564 = sr.bindings.values().iterator();
8565 while (bindings.hasNext()) {
8566 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008567 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008568 + ": shouldUnbind=" + b.hasBound);
8569 b.binder = null;
8570 b.requested = b.received = b.hasBound = false;
8571 }
8572 }
8573
Dianne Hackborn070783f2010-12-29 16:46:28 -08008574 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
8575 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008576 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008577 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008578 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008579 sr.crashCount, sr.shortName, app.pid);
8580 bringDownServiceLocked(sr, true);
8581 } else if (!allowRestart) {
8582 bringDownServiceLocked(sr, true);
8583 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008584 boolean canceled = scheduleServiceRestartLocked(sr, true);
8585
8586 // Should the service remain running? Note that in the
8587 // extreme case of so many attempts to deliver a command
8588 // that it failed, that we also will stop it here.
8589 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8590 if (sr.pendingStarts.size() == 0) {
8591 sr.startRequested = false;
8592 if (!hasClients) {
8593 // Whoops, no reason to restart!
8594 bringDownServiceLocked(sr, true);
8595 }
8596 }
8597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008598 }
8599 }
8600
8601 if (!allowRestart) {
8602 app.services.clear();
8603 }
8604 }
8605
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008606 // Make sure we have no more records on the stopping list.
8607 int i = mStoppingServices.size();
8608 while (i > 0) {
8609 i--;
8610 ServiceRecord sr = mStoppingServices.get(i);
8611 if (sr.app == app) {
8612 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008613 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008614 }
8615 }
8616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008617 app.executingServices.clear();
8618 }
8619
8620 private final void removeDyingProviderLocked(ProcessRecord proc,
8621 ContentProviderRecord cpr) {
8622 synchronized (cpr) {
8623 cpr.launchingApp = null;
8624 cpr.notifyAll();
8625 }
8626
8627 mProvidersByClass.remove(cpr.info.name);
8628 String names[] = cpr.info.authority.split(";");
8629 for (int j = 0; j < names.length; j++) {
8630 mProvidersByName.remove(names[j]);
8631 }
8632
8633 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8634 while (cit.hasNext()) {
8635 ProcessRecord capp = cit.next();
8636 if (!capp.persistent && capp.thread != null
8637 && capp.pid != 0
8638 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008639 Slog.i(TAG, "Kill " + capp.processName
8640 + " (pid " + capp.pid + "): provider " + cpr.info.name
8641 + " in dying process " + proc.processName);
8642 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8643 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 Process.killProcess(capp.pid);
8645 }
8646 }
8647
8648 mLaunchingProviders.remove(cpr);
8649 }
8650
8651 /**
8652 * Main code for cleaning up a process when it has gone away. This is
8653 * called both as a result of the process dying, or directly when stopping
8654 * a process when running in single process mode.
8655 */
8656 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8657 boolean restarting, int index) {
8658 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008659 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008660 }
8661
Dianne Hackborn36124872009-10-08 16:22:03 -07008662 mProcessesToGc.remove(app);
8663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008664 // Dismiss any open dialogs.
8665 if (app.crashDialog != null) {
8666 app.crashDialog.dismiss();
8667 app.crashDialog = null;
8668 }
8669 if (app.anrDialog != null) {
8670 app.anrDialog.dismiss();
8671 app.anrDialog = null;
8672 }
8673 if (app.waitDialog != null) {
8674 app.waitDialog.dismiss();
8675 app.waitDialog = null;
8676 }
8677
8678 app.crashing = false;
8679 app.notResponding = false;
8680
8681 app.resetPackageList();
8682 app.thread = null;
8683 app.forcingToForeground = null;
8684 app.foregroundServices = false;
8685
8686 killServicesLocked(app, true);
8687
8688 boolean restart = false;
8689
8690 int NL = mLaunchingProviders.size();
8691
8692 // Remove published content providers.
8693 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008694 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008695 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008696 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008697 cpr.provider = null;
8698 cpr.app = null;
8699
8700 // See if someone is waiting for this provider... in which
8701 // case we don't remove it, but just let it restart.
8702 int i = 0;
8703 if (!app.bad) {
8704 for (; i<NL; i++) {
8705 if (mLaunchingProviders.get(i) == cpr) {
8706 restart = true;
8707 break;
8708 }
8709 }
8710 } else {
8711 i = NL;
8712 }
8713
8714 if (i >= NL) {
8715 removeDyingProviderLocked(app, cpr);
8716 NL = mLaunchingProviders.size();
8717 }
8718 }
8719 app.pubProviders.clear();
8720 }
8721
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008722 // Take care of any launching providers waiting for this process.
8723 if (checkAppInLaunchingProvidersLocked(app, false)) {
8724 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008725 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008727 // Unregister from connected content providers.
8728 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008729 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008730 while (it.hasNext()) {
8731 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8732 cpr.clients.remove(app);
8733 }
8734 app.conProviders.clear();
8735 }
8736
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008737 // At this point there may be remaining entries in mLaunchingProviders
8738 // where we were the only one waiting, so they are no longer of use.
8739 // Look for these and clean up if found.
8740 // XXX Commented out for now. Trying to figure out a way to reproduce
8741 // the actual situation to identify what is actually going on.
8742 if (false) {
8743 for (int i=0; i<NL; i++) {
8744 ContentProviderRecord cpr = (ContentProviderRecord)
8745 mLaunchingProviders.get(i);
8746 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8747 synchronized (cpr) {
8748 cpr.launchingApp = null;
8749 cpr.notifyAll();
8750 }
8751 }
8752 }
8753 }
8754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008755 skipCurrentReceiverLocked(app);
8756
8757 // Unregister any receivers.
8758 if (app.receivers.size() > 0) {
8759 Iterator<ReceiverList> it = app.receivers.iterator();
8760 while (it.hasNext()) {
8761 removeReceiverLocked(it.next());
8762 }
8763 app.receivers.clear();
8764 }
8765
Christopher Tate181fafa2009-05-14 11:12:14 -07008766 // If the app is undergoing backup, tell the backup manager about it
8767 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008768 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008769 try {
8770 IBackupManager bm = IBackupManager.Stub.asInterface(
8771 ServiceManager.getService(Context.BACKUP_SERVICE));
8772 bm.agentDisconnected(app.info.packageName);
8773 } catch (RemoteException e) {
8774 // can't happen; backup manager is local
8775 }
8776 }
8777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008778 // If the caller is restarting this app, then leave it in its
8779 // current lists and let the caller take care of it.
8780 if (restarting) {
8781 return;
8782 }
8783
8784 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008785 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008786 "Removing non-persistent process during cleanup: " + app);
8787 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008788 if (mHeavyWeightProcess == app) {
8789 mHeavyWeightProcess = null;
8790 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008792 } else if (!app.removed) {
8793 // This app is persistent, so we need to keep its record around.
8794 // If it is not already on the pending app list, add it there
8795 // and start a new process for it.
8796 app.thread = null;
8797 app.forcingToForeground = null;
8798 app.foregroundServices = false;
8799 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8800 mPersistentStartingProcesses.add(app);
8801 restart = true;
8802 }
8803 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008804 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8805 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008806 mProcessesOnHold.remove(app);
8807
The Android Open Source Project4df24232009-03-05 14:34:35 -08008808 if (app == mHomeProcess) {
8809 mHomeProcess = null;
8810 }
8811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 if (restart) {
8813 // We have components that still need to be running in the
8814 // process, so re-launch it.
8815 mProcessNames.put(app.processName, app.info.uid, app);
8816 startProcessLocked(app, "restart", app.processName);
8817 } else if (app.pid > 0 && app.pid != MY_PID) {
8818 // Goodbye!
8819 synchronized (mPidsSelfLocked) {
8820 mPidsSelfLocked.remove(app.pid);
8821 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8822 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008823 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008824 }
8825 }
8826
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008827 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8828 // Look through the content providers we are waiting to have launched,
8829 // and if any run in this process then either schedule a restart of
8830 // the process or kill the client waiting for it if this process has
8831 // gone bad.
8832 int NL = mLaunchingProviders.size();
8833 boolean restart = false;
8834 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008835 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008836 if (cpr.launchingApp == app) {
8837 if (!alwaysBad && !app.bad) {
8838 restart = true;
8839 } else {
8840 removeDyingProviderLocked(app, cpr);
8841 NL = mLaunchingProviders.size();
8842 }
8843 }
8844 }
8845 return restart;
8846 }
8847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008848 // =========================================================
8849 // SERVICES
8850 // =========================================================
8851
8852 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8853 ActivityManager.RunningServiceInfo info =
8854 new ActivityManager.RunningServiceInfo();
8855 info.service = r.name;
8856 if (r.app != null) {
8857 info.pid = r.app.pid;
8858 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008859 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008860 info.process = r.processName;
8861 info.foreground = r.isForeground;
8862 info.activeSince = r.createTime;
8863 info.started = r.startRequested;
8864 info.clientCount = r.connections.size();
8865 info.crashCount = r.crashCount;
8866 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008867 if (r.isForeground) {
8868 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8869 }
8870 if (r.startRequested) {
8871 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8872 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008873 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008874 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8875 }
8876 if (r.app != null && r.app.persistent) {
8877 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8878 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008879
8880 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8881 for (int i=0; i<connl.size(); i++) {
8882 ConnectionRecord conn = connl.get(i);
8883 if (conn.clientLabel != 0) {
8884 info.clientPackage = conn.binding.client.info.packageName;
8885 info.clientLabel = conn.clientLabel;
8886 return info;
8887 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008888 }
8889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008890 return info;
8891 }
8892
8893 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8894 int flags) {
8895 synchronized (this) {
8896 ArrayList<ActivityManager.RunningServiceInfo> res
8897 = new ArrayList<ActivityManager.RunningServiceInfo>();
8898
8899 if (mServices.size() > 0) {
8900 Iterator<ServiceRecord> it = mServices.values().iterator();
8901 while (it.hasNext() && res.size() < maxNum) {
8902 res.add(makeRunningServiceInfoLocked(it.next()));
8903 }
8904 }
8905
8906 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8907 ServiceRecord r = mRestartingServices.get(i);
8908 ActivityManager.RunningServiceInfo info =
8909 makeRunningServiceInfoLocked(r);
8910 info.restarting = r.nextRestartTime;
8911 res.add(info);
8912 }
8913
8914 return res;
8915 }
8916 }
8917
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008918 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8919 synchronized (this) {
8920 ServiceRecord r = mServices.get(name);
8921 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008922 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8923 for (int i=0; i<conn.size(); i++) {
8924 if (conn.get(i).clientIntent != null) {
8925 return conn.get(i).clientIntent;
8926 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008927 }
8928 }
8929 }
8930 }
8931 return null;
8932 }
8933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008934 private final ServiceRecord findServiceLocked(ComponentName name,
8935 IBinder token) {
8936 ServiceRecord r = mServices.get(name);
8937 return r == token ? r : null;
8938 }
8939
8940 private final class ServiceLookupResult {
8941 final ServiceRecord record;
8942 final String permission;
8943
8944 ServiceLookupResult(ServiceRecord _record, String _permission) {
8945 record = _record;
8946 permission = _permission;
8947 }
8948 };
8949
8950 private ServiceLookupResult findServiceLocked(Intent service,
8951 String resolvedType) {
8952 ServiceRecord r = null;
8953 if (service.getComponent() != null) {
8954 r = mServices.get(service.getComponent());
8955 }
8956 if (r == null) {
8957 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8958 r = mServicesByIntent.get(filter);
8959 }
8960
8961 if (r == null) {
8962 try {
8963 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008964 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008965 service, resolvedType, 0);
8966 ServiceInfo sInfo =
8967 rInfo != null ? rInfo.serviceInfo : null;
8968 if (sInfo == null) {
8969 return null;
8970 }
8971
8972 ComponentName name = new ComponentName(
8973 sInfo.applicationInfo.packageName, sInfo.name);
8974 r = mServices.get(name);
8975 } catch (RemoteException ex) {
8976 // pm is in same process, this will never happen.
8977 }
8978 }
8979 if (r != null) {
8980 int callingPid = Binder.getCallingPid();
8981 int callingUid = Binder.getCallingUid();
8982 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008983 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008985 if (!r.exported) {
8986 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
8987 + " from pid=" + callingPid
8988 + ", uid=" + callingUid
8989 + " that is not exported from uid " + r.appInfo.uid);
8990 return new ServiceLookupResult(null, "not exported from uid "
8991 + r.appInfo.uid);
8992 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008993 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008994 + " from pid=" + callingPid
8995 + ", uid=" + callingUid
8996 + " requires " + r.permission);
8997 return new ServiceLookupResult(null, r.permission);
8998 }
8999 return new ServiceLookupResult(r, null);
9000 }
9001 return null;
9002 }
9003
9004 private class ServiceRestarter implements Runnable {
9005 private ServiceRecord mService;
9006
9007 void setService(ServiceRecord service) {
9008 mService = service;
9009 }
9010
9011 public void run() {
9012 synchronized(ActivityManagerService.this) {
9013 performServiceRestartLocked(mService);
9014 }
9015 }
9016 }
9017
9018 private ServiceLookupResult retrieveServiceLocked(Intent service,
9019 String resolvedType, int callingPid, int callingUid) {
9020 ServiceRecord r = null;
9021 if (service.getComponent() != null) {
9022 r = mServices.get(service.getComponent());
9023 }
9024 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9025 r = mServicesByIntent.get(filter);
9026 if (r == null) {
9027 try {
9028 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009029 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009030 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009031 ServiceInfo sInfo =
9032 rInfo != null ? rInfo.serviceInfo : null;
9033 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009034 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009035 ": not found");
9036 return null;
9037 }
9038
9039 ComponentName name = new ComponentName(
9040 sInfo.applicationInfo.packageName, sInfo.name);
9041 r = mServices.get(name);
9042 if (r == null) {
9043 filter = new Intent.FilterComparison(service.cloneFilter());
9044 ServiceRestarter res = new ServiceRestarter();
9045 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9046 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9047 synchronized (stats) {
9048 ss = stats.getServiceStatsLocked(
9049 sInfo.applicationInfo.uid, sInfo.packageName,
9050 sInfo.name);
9051 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009052 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009053 res.setService(r);
9054 mServices.put(name, r);
9055 mServicesByIntent.put(filter, r);
9056
9057 // Make sure this component isn't in the pending list.
9058 int N = mPendingServices.size();
9059 for (int i=0; i<N; i++) {
9060 ServiceRecord pr = mPendingServices.get(i);
9061 if (pr.name.equals(name)) {
9062 mPendingServices.remove(i);
9063 i--;
9064 N--;
9065 }
9066 }
9067 }
9068 } catch (RemoteException ex) {
9069 // pm is in same process, this will never happen.
9070 }
9071 }
9072 if (r != null) {
9073 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009074 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009075 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009076 if (!r.exported) {
9077 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9078 + " from pid=" + callingPid
9079 + ", uid=" + callingUid
9080 + " that is not exported from uid " + r.appInfo.uid);
9081 return new ServiceLookupResult(null, "not exported from uid "
9082 + r.appInfo.uid);
9083 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009084 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009085 + " from pid=" + callingPid
9086 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009087 + " requires " + r.permission);
9088 return new ServiceLookupResult(null, r.permission);
9089 }
9090 return new ServiceLookupResult(r, null);
9091 }
9092 return null;
9093 }
9094
Dianne Hackborn287952c2010-09-22 22:34:31 -07009095 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9096 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9097 + why + " of " + r + " in app " + r.app);
9098 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9099 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009100 long now = SystemClock.uptimeMillis();
9101 if (r.executeNesting == 0 && r.app != null) {
9102 if (r.app.executingServices.size() == 0) {
9103 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9104 msg.obj = r.app;
9105 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9106 }
9107 r.app.executingServices.add(r);
9108 }
9109 r.executeNesting++;
9110 r.executingStart = now;
9111 }
9112
9113 private final void sendServiceArgsLocked(ServiceRecord r,
9114 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009115 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009116 if (N == 0) {
9117 return;
9118 }
9119
Dianne Hackborn39792d22010-08-19 18:01:52 -07009120 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009121 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009122 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009123 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9124 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009125 if (si.intent == null && N > 1) {
9126 // If somehow we got a dummy null intent in the middle,
9127 // then skip it. DO NOT skip a null intent when it is
9128 // the only one in the list -- this is to support the
9129 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009130 continue;
9131 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009132 si.deliveredTime = SystemClock.uptimeMillis();
9133 r.deliveredStarts.add(si);
9134 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009135 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009136 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009137 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009138 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009139 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009140 if (!oomAdjusted) {
9141 oomAdjusted = true;
9142 updateOomAdjLocked(r.app);
9143 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009144 int flags = 0;
9145 if (si.deliveryCount > 0) {
9146 flags |= Service.START_FLAG_RETRY;
9147 }
9148 if (si.doneExecutingCount > 0) {
9149 flags |= Service.START_FLAG_REDELIVERY;
9150 }
9151 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009152 } catch (RemoteException e) {
9153 // Remote process gone... we'll let the normal cleanup take
9154 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009155 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009156 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009157 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009158 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009159 break;
9160 }
9161 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009162 }
9163
9164 private final boolean requestServiceBindingLocked(ServiceRecord r,
9165 IntentBindRecord i, boolean rebind) {
9166 if (r.app == null || r.app.thread == null) {
9167 // If service is not currently running, can't yet bind.
9168 return false;
9169 }
9170 if ((!i.requested || rebind) && i.apps.size() > 0) {
9171 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009172 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9174 if (!rebind) {
9175 i.requested = true;
9176 }
9177 i.hasBound = true;
9178 i.doRebind = false;
9179 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009180 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 return false;
9182 }
9183 }
9184 return true;
9185 }
9186
9187 private final void requestServiceBindingsLocked(ServiceRecord r) {
9188 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9189 while (bindings.hasNext()) {
9190 IntentBindRecord i = bindings.next();
9191 if (!requestServiceBindingLocked(r, i, false)) {
9192 break;
9193 }
9194 }
9195 }
9196
9197 private final void realStartServiceLocked(ServiceRecord r,
9198 ProcessRecord app) throws RemoteException {
9199 if (app.thread == null) {
9200 throw new RemoteException();
9201 }
9202
9203 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009204 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009205
9206 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009207 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009208 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009209
9210 boolean created = false;
9211 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009212 mStringBuilder.setLength(0);
9213 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009214 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009215 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009216 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009217 synchronized (r.stats.getBatteryStats()) {
9218 r.stats.startLaunchedLocked();
9219 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009220 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009222 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009223 created = true;
9224 } finally {
9225 if (!created) {
9226 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009227 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009228 }
9229 }
9230
9231 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009232
9233 // If the service is in the started state, and there are no
9234 // pending arguments, then fake up one so its onStartCommand() will
9235 // be called.
9236 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9237 r.lastStartId++;
9238 if (r.lastStartId < 1) {
9239 r.lastStartId = 1;
9240 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009241 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009242 }
9243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009244 sendServiceArgsLocked(r, true);
9245 }
9246
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009247 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9248 boolean allowCancel) {
9249 boolean canceled = false;
9250
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009251 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009252 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009253 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009254
Dianne Hackborn070783f2010-12-29 16:46:28 -08009255 if ((r.serviceInfo.applicationInfo.flags
9256 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9257 minDuration /= 4;
9258 }
9259
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009260 // Any delivered but not yet finished starts should be put back
9261 // on the pending list.
9262 final int N = r.deliveredStarts.size();
9263 if (N > 0) {
9264 for (int i=N-1; i>=0; i--) {
9265 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009266 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009267 if (si.intent == null) {
9268 // We'll generate this again if needed.
9269 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9270 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9271 r.pendingStarts.add(0, si);
9272 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9273 dur *= 2;
9274 if (minDuration < dur) minDuration = dur;
9275 if (resetTime < dur) resetTime = dur;
9276 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009277 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009278 + r.name);
9279 canceled = true;
9280 }
9281 }
9282 r.deliveredStarts.clear();
9283 }
9284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285 r.totalRestartCount++;
9286 if (r.restartDelay == 0) {
9287 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009288 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009289 } else {
9290 // If it has been a "reasonably long time" since the service
9291 // was started, then reset our restart duration back to
9292 // the beginning, so we don't infinitely increase the duration
9293 // on a service that just occasionally gets killed (which is
9294 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009295 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009296 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009297 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009298 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009299 if ((r.serviceInfo.applicationInfo.flags
9300 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9301 // Services in peristent processes will restart much more
9302 // quickly, since they are pretty important. (Think SystemUI).
9303 r.restartDelay += minDuration/2;
9304 } else {
9305 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9306 if (r.restartDelay < minDuration) {
9307 r.restartDelay = minDuration;
9308 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009310 }
9311 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009312
9313 r.nextRestartTime = now + r.restartDelay;
9314
9315 // Make sure that we don't end up restarting a bunch of services
9316 // all at the same time.
9317 boolean repeat;
9318 do {
9319 repeat = false;
9320 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9321 ServiceRecord r2 = mRestartingServices.get(i);
9322 if (r2 != r && r.nextRestartTime
9323 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9324 && r.nextRestartTime
9325 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9326 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9327 r.restartDelay = r.nextRestartTime - now;
9328 repeat = true;
9329 break;
9330 }
9331 }
9332 } while (repeat);
9333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009334 if (!mRestartingServices.contains(r)) {
9335 mRestartingServices.add(r);
9336 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009337
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009338 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009341 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009342 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009343 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009344 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009345 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009346 r.shortName, r.restartDelay);
9347
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009348 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009349 }
9350
9351 final void performServiceRestartLocked(ServiceRecord r) {
9352 if (!mRestartingServices.contains(r)) {
9353 return;
9354 }
9355 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9356 }
9357
9358 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9359 if (r.restartDelay == 0) {
9360 return false;
9361 }
9362 r.resetRestartCounter();
9363 mRestartingServices.remove(r);
9364 mHandler.removeCallbacks(r.restarter);
9365 return true;
9366 }
9367
9368 private final boolean bringUpServiceLocked(ServiceRecord r,
9369 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009370 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009371 //r.dump(" ");
9372
Dianne Hackborn36124872009-10-08 16:22:03 -07009373 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009374 sendServiceArgsLocked(r, false);
9375 return true;
9376 }
9377
9378 if (!whileRestarting && r.restartDelay > 0) {
9379 // If waiting for a restart, then do nothing.
9380 return true;
9381 }
9382
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009383 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009384
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009385 // We are now bringing the service up, so no longer in the
9386 // restarting state.
9387 mRestartingServices.remove(r);
9388
Dianne Hackborne7f97212011-02-24 14:40:20 -08009389 // Service is now being launched, its package can't be stopped.
9390 try {
9391 AppGlobals.getPackageManager().setPackageStoppedState(
9392 r.packageName, false);
9393 } catch (RemoteException e) {
9394 }
9395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009396 final String appName = r.processName;
9397 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9398 if (app != null && app.thread != null) {
9399 try {
9400 realStartServiceLocked(r, app);
9401 return true;
9402 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009403 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009404 }
9405
9406 // If a dead object exception was thrown -- fall through to
9407 // restart the application.
9408 }
9409
Dianne Hackborn36124872009-10-08 16:22:03 -07009410 // Not running -- get it started, and enqueue this service record
9411 // to be executed when the app comes up.
9412 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9413 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009414 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009415 + r.appInfo.packageName + "/"
9416 + r.appInfo.uid + " for service "
9417 + r.intent.getIntent() + ": process is bad");
9418 bringDownServiceLocked(r, true);
9419 return false;
9420 }
9421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009422 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009423 mPendingServices.add(r);
9424 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009426 return true;
9427 }
9428
9429 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009430 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009431 //r.dump(" ");
9432
9433 // Does it still need to run?
9434 if (!force && r.startRequested) {
9435 return;
9436 }
9437 if (r.connections.size() > 0) {
9438 if (!force) {
9439 // XXX should probably keep a count of the number of auto-create
9440 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009441 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009442 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009443 ArrayList<ConnectionRecord> cr = it.next();
9444 for (int i=0; i<cr.size(); i++) {
9445 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9446 return;
9447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009448 }
9449 }
9450 }
9451
9452 // Report to all of the connections that the service is no longer
9453 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009454 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009455 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009456 ArrayList<ConnectionRecord> c = it.next();
9457 for (int i=0; i<c.size(); i++) {
9458 try {
9459 c.get(i).conn.connected(r.name, null);
9460 } catch (Exception e) {
9461 Slog.w(TAG, "Failure disconnecting service " + r.name +
9462 " to connection " + c.get(i).conn.asBinder() +
9463 " (in " + c.get(i).binding.client.processName + ")", e);
9464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009465 }
9466 }
9467 }
9468
9469 // Tell the service that it has been unbound.
9470 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9471 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9472 while (it.hasNext()) {
9473 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009474 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009475 + ": hasBound=" + ibr.hasBound);
9476 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9477 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009478 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 updateOomAdjLocked(r.app);
9480 ibr.hasBound = false;
9481 r.app.thread.scheduleUnbindService(r,
9482 ibr.intent.getIntent());
9483 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009484 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009485 + r.shortName, e);
9486 serviceDoneExecutingLocked(r, true);
9487 }
9488 }
9489 }
9490 }
9491
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009492 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009493 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009494 System.identityHashCode(r), r.shortName,
9495 (r.app != null) ? r.app.pid : -1);
9496
9497 mServices.remove(r.name);
9498 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009499 r.totalRestartCount = 0;
9500 unscheduleServiceRestartLocked(r);
9501
9502 // Also make sure it is not on the pending list.
9503 int N = mPendingServices.size();
9504 for (int i=0; i<N; i++) {
9505 if (mPendingServices.get(i) == r) {
9506 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009507 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009508 i--;
9509 N--;
9510 }
9511 }
9512
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009513 r.cancelNotification();
9514 r.isForeground = false;
9515 r.foregroundId = 0;
9516 r.foregroundNoti = null;
9517
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009518 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009519 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009520 r.pendingStarts.clear();
9521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009522 if (r.app != null) {
9523 synchronized (r.stats.getBatteryStats()) {
9524 r.stats.stopLaunchedLocked();
9525 }
9526 r.app.services.remove(r);
9527 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009528 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009529 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009530 mStoppingServices.add(r);
9531 updateOomAdjLocked(r.app);
9532 r.app.thread.scheduleStopService(r);
9533 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009534 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009535 + r.shortName, e);
9536 serviceDoneExecutingLocked(r, true);
9537 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009538 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009539 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009540 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009541 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009542 }
9543 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009544 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009545 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009546 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -08009547
9548 if (r.bindings.size() > 0) {
9549 r.bindings.clear();
9550 }
9551
9552 if (r.restarter instanceof ServiceRestarter) {
9553 ((ServiceRestarter)r.restarter).setService(null);
9554 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009555 }
9556
9557 ComponentName startServiceLocked(IApplicationThread caller,
9558 Intent service, String resolvedType,
9559 int callingPid, int callingUid) {
9560 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009561 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009562 + " type=" + resolvedType + " args=" + service.getExtras());
9563
9564 if (caller != null) {
9565 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9566 if (callerApp == null) {
9567 throw new SecurityException(
9568 "Unable to find app for caller " + caller
9569 + " (pid=" + Binder.getCallingPid()
9570 + ") when starting service " + service);
9571 }
9572 }
9573
9574 ServiceLookupResult res =
9575 retrieveServiceLocked(service, resolvedType,
9576 callingPid, callingUid);
9577 if (res == null) {
9578 return null;
9579 }
9580 if (res.record == null) {
9581 return new ComponentName("!", res.permission != null
9582 ? res.permission : "private to package");
9583 }
9584 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009585 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9586 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009587 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009588 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009589 }
9590 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009591 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009592 r.lastStartId++;
9593 if (r.lastStartId < 1) {
9594 r.lastStartId = 1;
9595 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009596 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9597 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598 r.lastActivity = SystemClock.uptimeMillis();
9599 synchronized (r.stats.getBatteryStats()) {
9600 r.stats.startRunningLocked();
9601 }
9602 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9603 return new ComponentName("!", "Service process is bad");
9604 }
9605 return r.name;
9606 }
9607 }
9608
9609 public ComponentName startService(IApplicationThread caller, Intent service,
9610 String resolvedType) {
9611 // Refuse possible leaked file descriptors
9612 if (service != null && service.hasFileDescriptors() == true) {
9613 throw new IllegalArgumentException("File descriptors passed in Intent");
9614 }
9615
9616 synchronized(this) {
9617 final int callingPid = Binder.getCallingPid();
9618 final int callingUid = Binder.getCallingUid();
9619 final long origId = Binder.clearCallingIdentity();
9620 ComponentName res = startServiceLocked(caller, service,
9621 resolvedType, callingPid, callingUid);
9622 Binder.restoreCallingIdentity(origId);
9623 return res;
9624 }
9625 }
9626
9627 ComponentName startServiceInPackage(int uid,
9628 Intent service, String resolvedType) {
9629 synchronized(this) {
9630 final long origId = Binder.clearCallingIdentity();
9631 ComponentName res = startServiceLocked(null, service,
9632 resolvedType, -1, uid);
9633 Binder.restoreCallingIdentity(origId);
9634 return res;
9635 }
9636 }
9637
9638 public int stopService(IApplicationThread caller, Intent service,
9639 String resolvedType) {
9640 // Refuse possible leaked file descriptors
9641 if (service != null && service.hasFileDescriptors() == true) {
9642 throw new IllegalArgumentException("File descriptors passed in Intent");
9643 }
9644
9645 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009646 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009647 + " type=" + resolvedType);
9648
9649 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9650 if (caller != null && callerApp == null) {
9651 throw new SecurityException(
9652 "Unable to find app for caller " + caller
9653 + " (pid=" + Binder.getCallingPid()
9654 + ") when stopping service " + service);
9655 }
9656
9657 // If this service is active, make sure it is stopped.
9658 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9659 if (r != null) {
9660 if (r.record != null) {
9661 synchronized (r.record.stats.getBatteryStats()) {
9662 r.record.stats.stopRunningLocked();
9663 }
9664 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009665 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009666 final long origId = Binder.clearCallingIdentity();
9667 bringDownServiceLocked(r.record, false);
9668 Binder.restoreCallingIdentity(origId);
9669 return 1;
9670 }
9671 return -1;
9672 }
9673 }
9674
9675 return 0;
9676 }
9677
9678 public IBinder peekService(Intent service, String resolvedType) {
9679 // Refuse possible leaked file descriptors
9680 if (service != null && service.hasFileDescriptors() == true) {
9681 throw new IllegalArgumentException("File descriptors passed in Intent");
9682 }
9683
9684 IBinder ret = null;
9685
9686 synchronized(this) {
9687 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9688
9689 if (r != null) {
9690 // r.record is null if findServiceLocked() failed the caller permission check
9691 if (r.record == null) {
9692 throw new SecurityException(
9693 "Permission Denial: Accessing service " + r.record.name
9694 + " from pid=" + Binder.getCallingPid()
9695 + ", uid=" + Binder.getCallingUid()
9696 + " requires " + r.permission);
9697 }
9698 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9699 if (ib != null) {
9700 ret = ib.binder;
9701 }
9702 }
9703 }
9704
9705 return ret;
9706 }
9707
9708 public boolean stopServiceToken(ComponentName className, IBinder token,
9709 int startId) {
9710 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009711 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009712 + " " + token + " startId=" + startId);
9713 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009714 if (r != null) {
9715 if (startId >= 0) {
9716 // Asked to only stop if done with all work. Note that
9717 // to avoid leaks, we will take this as dropping all
9718 // start items up to and including this one.
9719 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9720 if (si != null) {
9721 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009722 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9723 cur.removeUriPermissionsLocked();
9724 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009725 break;
9726 }
9727 }
9728 }
9729
9730 if (r.lastStartId != startId) {
9731 return false;
9732 }
9733
9734 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009735 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009736 + " is last, but have " + r.deliveredStarts.size()
9737 + " remaining args");
9738 }
9739 }
9740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009741 synchronized (r.stats.getBatteryStats()) {
9742 r.stats.stopRunningLocked();
9743 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009744 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009745 }
9746 final long origId = Binder.clearCallingIdentity();
9747 bringDownServiceLocked(r, false);
9748 Binder.restoreCallingIdentity(origId);
9749 return true;
9750 }
9751 }
9752 return false;
9753 }
9754
9755 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009756 int id, Notification notification, boolean removeNotification) {
9757 final long origId = Binder.clearCallingIdentity();
9758 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009759 synchronized(this) {
9760 ServiceRecord r = findServiceLocked(className, token);
9761 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009762 if (id != 0) {
9763 if (notification == null) {
9764 throw new IllegalArgumentException("null notification");
9765 }
9766 if (r.foregroundId != id) {
9767 r.cancelNotification();
9768 r.foregroundId = id;
9769 }
9770 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9771 r.foregroundNoti = notification;
9772 r.isForeground = true;
9773 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009774 if (r.app != null) {
9775 updateServiceForegroundLocked(r.app, true);
9776 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009777 } else {
9778 if (r.isForeground) {
9779 r.isForeground = false;
9780 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009781 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009782 updateServiceForegroundLocked(r.app, true);
9783 }
9784 }
9785 if (removeNotification) {
9786 r.cancelNotification();
9787 r.foregroundId = 0;
9788 r.foregroundNoti = null;
9789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009790 }
9791 }
9792 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009793 } finally {
9794 Binder.restoreCallingIdentity(origId);
9795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009796 }
9797
9798 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9799 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009800 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009801 if (sr.isForeground) {
9802 anyForeground = true;
9803 break;
9804 }
9805 }
9806 if (anyForeground != proc.foregroundServices) {
9807 proc.foregroundServices = anyForeground;
9808 if (oomAdj) {
9809 updateOomAdjLocked();
9810 }
9811 }
9812 }
9813
9814 public int bindService(IApplicationThread caller, IBinder token,
9815 Intent service, String resolvedType,
9816 IServiceConnection connection, int flags) {
9817 // Refuse possible leaked file descriptors
9818 if (service != null && service.hasFileDescriptors() == true) {
9819 throw new IllegalArgumentException("File descriptors passed in Intent");
9820 }
9821
9822 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009823 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009824 + " type=" + resolvedType + " conn=" + connection.asBinder()
9825 + " flags=0x" + Integer.toHexString(flags));
9826 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9827 if (callerApp == null) {
9828 throw new SecurityException(
9829 "Unable to find app for caller " + caller
9830 + " (pid=" + Binder.getCallingPid()
9831 + ") when binding service " + service);
9832 }
9833
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009834 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009835 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009836 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009837 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009838 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839 return 0;
9840 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009841 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009842 }
9843
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009844 int clientLabel = 0;
9845 PendingIntent clientIntent = null;
9846
9847 if (callerApp.info.uid == Process.SYSTEM_UID) {
9848 // Hacky kind of thing -- allow system stuff to tell us
9849 // what they are, so we can report this elsewhere for
9850 // others to know why certain services are running.
9851 try {
9852 clientIntent = (PendingIntent)service.getParcelableExtra(
9853 Intent.EXTRA_CLIENT_INTENT);
9854 } catch (RuntimeException e) {
9855 }
9856 if (clientIntent != null) {
9857 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9858 if (clientLabel != 0) {
9859 // There are no useful extras in the intent, trash them.
9860 // System code calling with this stuff just needs to know
9861 // this will happen.
9862 service = service.cloneFilter();
9863 }
9864 }
9865 }
9866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009867 ServiceLookupResult res =
9868 retrieveServiceLocked(service, resolvedType,
9869 Binder.getCallingPid(), Binder.getCallingUid());
9870 if (res == null) {
9871 return 0;
9872 }
9873 if (res.record == null) {
9874 return -1;
9875 }
9876 ServiceRecord s = res.record;
9877
9878 final long origId = Binder.clearCallingIdentity();
9879
9880 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009881 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009882 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009883 }
9884
9885 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9886 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009887 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009888
9889 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009890 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9891 if (clist == null) {
9892 clist = new ArrayList<ConnectionRecord>();
9893 s.connections.put(binder, clist);
9894 }
9895 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009896 b.connections.add(c);
9897 if (activity != null) {
9898 if (activity.connections == null) {
9899 activity.connections = new HashSet<ConnectionRecord>();
9900 }
9901 activity.connections.add(c);
9902 }
9903 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009904 clist = mServiceConnections.get(binder);
9905 if (clist == null) {
9906 clist = new ArrayList<ConnectionRecord>();
9907 mServiceConnections.put(binder, clist);
9908 }
9909 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009910
9911 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9912 s.lastActivity = SystemClock.uptimeMillis();
9913 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9914 return 0;
9915 }
9916 }
9917
9918 if (s.app != null) {
9919 // This could have made the service more important.
9920 updateOomAdjLocked(s.app);
9921 }
9922
Joe Onorato8a9b2202010-02-26 18:56:32 -08009923 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009924 + ": received=" + b.intent.received
9925 + " apps=" + b.intent.apps.size()
9926 + " doRebind=" + b.intent.doRebind);
9927
9928 if (s.app != null && b.intent.received) {
9929 // Service is already running, so we can immediately
9930 // publish the connection.
9931 try {
9932 c.conn.connected(s.name, b.intent.binder);
9933 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009934 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009935 + " to connection " + c.conn.asBinder()
9936 + " (in " + c.binding.client.processName + ")", e);
9937 }
9938
9939 // If this is the first app connected back to this binding,
9940 // and the service had previously asked to be told when
9941 // rebound, then do so.
9942 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9943 requestServiceBindingLocked(s, b.intent, true);
9944 }
9945 } else if (!b.intent.requested) {
9946 requestServiceBindingLocked(s, b.intent, false);
9947 }
9948
9949 Binder.restoreCallingIdentity(origId);
9950 }
9951
9952 return 1;
9953 }
9954
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009955 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009956 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009957 IBinder binder = c.conn.asBinder();
9958 AppBindRecord b = c.binding;
9959 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009960 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9961 if (clist != null) {
9962 clist.remove(c);
9963 if (clist.size() == 0) {
9964 s.connections.remove(binder);
9965 }
9966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009967 b.connections.remove(c);
9968 if (c.activity != null && c.activity != skipAct) {
9969 if (c.activity.connections != null) {
9970 c.activity.connections.remove(c);
9971 }
9972 }
9973 if (b.client != skipApp) {
9974 b.client.connections.remove(c);
9975 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009976 clist = mServiceConnections.get(binder);
9977 if (clist != null) {
9978 clist.remove(c);
9979 if (clist.size() == 0) {
9980 mServiceConnections.remove(binder);
9981 }
9982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009983
9984 if (b.connections.size() == 0) {
9985 b.intent.apps.remove(b.client);
9986 }
9987
Joe Onorato8a9b2202010-02-26 18:56:32 -08009988 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009989 + ": shouldUnbind=" + b.intent.hasBound);
9990 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9991 && b.intent.hasBound) {
9992 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009993 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009994 updateOomAdjLocked(s.app);
9995 b.intent.hasBound = false;
9996 // Assume the client doesn't want to know about a rebind;
9997 // we will deal with that later if it asks for one.
9998 b.intent.doRebind = false;
9999 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10000 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010001 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010002 serviceDoneExecutingLocked(s, true);
10003 }
10004 }
10005
10006 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10007 bringDownServiceLocked(s, false);
10008 }
10009 }
10010
10011 public boolean unbindService(IServiceConnection connection) {
10012 synchronized (this) {
10013 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010014 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010015 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10016 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010017 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010018 + connection.asBinder());
10019 return false;
10020 }
10021
10022 final long origId = Binder.clearCallingIdentity();
10023
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010024 while (clist.size() > 0) {
10025 ConnectionRecord r = clist.get(0);
10026 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010027
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010028 if (r.binding.service.app != null) {
10029 // This could have made the service less important.
10030 updateOomAdjLocked(r.binding.service.app);
10031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010032 }
10033
10034 Binder.restoreCallingIdentity(origId);
10035 }
10036
10037 return true;
10038 }
10039
10040 public void publishService(IBinder token, Intent intent, IBinder service) {
10041 // Refuse possible leaked file descriptors
10042 if (intent != null && intent.hasFileDescriptors() == true) {
10043 throw new IllegalArgumentException("File descriptors passed in Intent");
10044 }
10045
10046 synchronized(this) {
10047 if (!(token instanceof ServiceRecord)) {
10048 throw new IllegalArgumentException("Invalid service token");
10049 }
10050 ServiceRecord r = (ServiceRecord)token;
10051
10052 final long origId = Binder.clearCallingIdentity();
10053
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010054 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010055 + " " + intent + ": " + service);
10056 if (r != null) {
10057 Intent.FilterComparison filter
10058 = new Intent.FilterComparison(intent);
10059 IntentBindRecord b = r.bindings.get(filter);
10060 if (b != null && !b.received) {
10061 b.binder = service;
10062 b.requested = true;
10063 b.received = true;
10064 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010065 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 = r.connections.values().iterator();
10067 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010068 ArrayList<ConnectionRecord> clist = it.next();
10069 for (int i=0; i<clist.size(); i++) {
10070 ConnectionRecord c = clist.get(i);
10071 if (!filter.equals(c.binding.intent.intent)) {
10072 if (DEBUG_SERVICE) Slog.v(
10073 TAG, "Not publishing to: " + c);
10074 if (DEBUG_SERVICE) Slog.v(
10075 TAG, "Bound intent: " + c.binding.intent.intent);
10076 if (DEBUG_SERVICE) Slog.v(
10077 TAG, "Published intent: " + intent);
10078 continue;
10079 }
10080 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10081 try {
10082 c.conn.connected(r.name, service);
10083 } catch (Exception e) {
10084 Slog.w(TAG, "Failure sending service " + r.name +
10085 " to connection " + c.conn.asBinder() +
10086 " (in " + c.binding.client.processName + ")", e);
10087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010088 }
10089 }
10090 }
10091 }
10092
10093 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10094
10095 Binder.restoreCallingIdentity(origId);
10096 }
10097 }
10098 }
10099
10100 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10101 // Refuse possible leaked file descriptors
10102 if (intent != null && intent.hasFileDescriptors() == true) {
10103 throw new IllegalArgumentException("File descriptors passed in Intent");
10104 }
10105
10106 synchronized(this) {
10107 if (!(token instanceof ServiceRecord)) {
10108 throw new IllegalArgumentException("Invalid service token");
10109 }
10110 ServiceRecord r = (ServiceRecord)token;
10111
10112 final long origId = Binder.clearCallingIdentity();
10113
10114 if (r != null) {
10115 Intent.FilterComparison filter
10116 = new Intent.FilterComparison(intent);
10117 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010118 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010119 + " at " + b + ": apps="
10120 + (b != null ? b.apps.size() : 0));
10121 if (b != null) {
10122 if (b.apps.size() > 0) {
10123 // Applications have already bound since the last
10124 // unbind, so just rebind right here.
10125 requestServiceBindingLocked(r, b, true);
10126 } else {
10127 // Note to tell the service the next time there is
10128 // a new client.
10129 b.doRebind = true;
10130 }
10131 }
10132
10133 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10134
10135 Binder.restoreCallingIdentity(origId);
10136 }
10137 }
10138 }
10139
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010140 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010141 synchronized(this) {
10142 if (!(token instanceof ServiceRecord)) {
10143 throw new IllegalArgumentException("Invalid service token");
10144 }
10145 ServiceRecord r = (ServiceRecord)token;
10146 boolean inStopping = mStoppingServices.contains(token);
10147 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010148 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010149 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010150 + " with incorrect token: given " + token
10151 + ", expected " + r);
10152 return;
10153 }
10154
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010155 if (type == 1) {
10156 // This is a call from a service start... take care of
10157 // book-keeping.
10158 r.callStart = true;
10159 switch (res) {
10160 case Service.START_STICKY_COMPATIBILITY:
10161 case Service.START_STICKY: {
10162 // We are done with the associated start arguments.
10163 r.findDeliveredStart(startId, true);
10164 // Don't stop if killed.
10165 r.stopIfKilled = false;
10166 break;
10167 }
10168 case Service.START_NOT_STICKY: {
10169 // We are done with the associated start arguments.
10170 r.findDeliveredStart(startId, true);
10171 if (r.lastStartId == startId) {
10172 // There is no more work, and this service
10173 // doesn't want to hang around if killed.
10174 r.stopIfKilled = true;
10175 }
10176 break;
10177 }
10178 case Service.START_REDELIVER_INTENT: {
10179 // We'll keep this item until they explicitly
10180 // call stop for it, but keep track of the fact
10181 // that it was delivered.
10182 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10183 if (si != null) {
10184 si.deliveryCount = 0;
10185 si.doneExecutingCount++;
10186 // Don't stop if killed.
10187 r.stopIfKilled = true;
10188 }
10189 break;
10190 }
10191 default:
10192 throw new IllegalArgumentException(
10193 "Unknown service start result: " + res);
10194 }
10195 if (res == Service.START_STICKY_COMPATIBILITY) {
10196 r.callStart = false;
10197 }
10198 }
10199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010200 final long origId = Binder.clearCallingIdentity();
10201 serviceDoneExecutingLocked(r, inStopping);
10202 Binder.restoreCallingIdentity(origId);
10203 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010204 Slog.w(TAG, "Done executing unknown service from pid "
10205 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010206 }
10207 }
10208 }
10209
10210 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010211 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10212 + ": nesting=" + r.executeNesting
10213 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010214 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010215 r.executeNesting--;
10216 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010217 if (DEBUG_SERVICE) Slog.v(TAG,
10218 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010219 r.app.executingServices.remove(r);
10220 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010221 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10222 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010223 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10224 }
10225 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010226 if (DEBUG_SERVICE) Slog.v(TAG,
10227 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010228 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010229 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 }
10231 updateOomAdjLocked(r.app);
10232 }
10233 }
10234
10235 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010236 String anrMessage = null;
10237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010238 synchronized(this) {
10239 if (proc.executingServices.size() == 0 || proc.thread == null) {
10240 return;
10241 }
10242 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10243 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10244 ServiceRecord timeout = null;
10245 long nextTime = 0;
10246 while (it.hasNext()) {
10247 ServiceRecord sr = it.next();
10248 if (sr.executingStart < maxTime) {
10249 timeout = sr;
10250 break;
10251 }
10252 if (sr.executingStart > nextTime) {
10253 nextTime = sr.executingStart;
10254 }
10255 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010256 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010257 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010258 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010259 } else {
10260 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10261 msg.obj = proc;
10262 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10263 }
10264 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010265
10266 if (anrMessage != null) {
10267 appNotResponding(proc, null, null, anrMessage);
10268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010269 }
10270
10271 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010272 // BACKUP AND RESTORE
10273 // =========================================================
10274
10275 // Cause the target app to be launched if necessary and its backup agent
10276 // instantiated. The backup agent will invoke backupAgentCreated() on the
10277 // activity manager to announce its creation.
10278 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010279 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010280 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10281
10282 synchronized(this) {
10283 // !!! TODO: currently no check here that we're already bound
10284 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10285 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10286 synchronized (stats) {
10287 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10288 }
10289
Dianne Hackborne7f97212011-02-24 14:40:20 -080010290 // Backup agent is now in use, its package can't be stopped.
10291 try {
10292 AppGlobals.getPackageManager().setPackageStoppedState(
10293 app.packageName, false);
10294 } catch (RemoteException e) {
10295 }
10296
Christopher Tate181fafa2009-05-14 11:12:14 -070010297 BackupRecord r = new BackupRecord(ss, app, backupMode);
10298 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10299 // startProcessLocked() returns existing proc's record if it's already running
10300 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010301 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010302 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010303 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010304 return false;
10305 }
10306
10307 r.app = proc;
10308 mBackupTarget = r;
10309 mBackupAppName = app.packageName;
10310
Christopher Tate6fa95972009-06-05 18:43:55 -070010311 // Try not to kill the process during backup
10312 updateOomAdjLocked(proc);
10313
Christopher Tate181fafa2009-05-14 11:12:14 -070010314 // If the process is already attached, schedule the creation of the backup agent now.
10315 // If it is not yet live, this will be done when it attaches to the framework.
10316 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010317 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010318 try {
10319 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10320 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010321 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010322 }
10323 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010324 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010325 }
10326 // Invariants: at this point, the target app process exists and the application
10327 // is either already running or in the process of coming up. mBackupTarget and
10328 // mBackupAppName describe the app, so that when it binds back to the AM we
10329 // know that it's scheduled for a backup-agent operation.
10330 }
10331
10332 return true;
10333 }
10334
10335 // A backup agent has just come up
10336 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010337 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010338 + " = " + agent);
10339
10340 synchronized(this) {
10341 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010342 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010343 return;
10344 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010345 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010346
Dianne Hackborn06740692010-09-22 22:46:21 -070010347 long oldIdent = Binder.clearCallingIdentity();
10348 try {
10349 IBackupManager bm = IBackupManager.Stub.asInterface(
10350 ServiceManager.getService(Context.BACKUP_SERVICE));
10351 bm.agentConnected(agentPackageName, agent);
10352 } catch (RemoteException e) {
10353 // can't happen; the backup manager service is local
10354 } catch (Exception e) {
10355 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10356 e.printStackTrace();
10357 } finally {
10358 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010359 }
10360 }
10361
10362 // done with this agent
10363 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010364 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010365 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010366 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010367 return;
10368 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010369
10370 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010371 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010372 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010373 return;
10374 }
10375
Christopher Tate181fafa2009-05-14 11:12:14 -070010376 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010377 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010378 return;
10379 }
10380
Christopher Tate6fa95972009-06-05 18:43:55 -070010381 ProcessRecord proc = mBackupTarget.app;
10382 mBackupTarget = null;
10383 mBackupAppName = null;
10384
10385 // Not backing this app up any more; reset its OOM adjustment
10386 updateOomAdjLocked(proc);
10387
Christopher Tatec7b31e32009-06-10 15:49:30 -070010388 // If the app crashed during backup, 'thread' will be null here
10389 if (proc.thread != null) {
10390 try {
10391 proc.thread.scheduleDestroyBackupAgent(appInfo);
10392 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010393 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010394 e.printStackTrace();
10395 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010396 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010397 }
10398 }
10399 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010400 // BROADCASTS
10401 // =========================================================
10402
Josh Bartel7f208742010-02-25 11:01:44 -060010403 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010404 List cur) {
10405 final ContentResolver resolver = mContext.getContentResolver();
10406 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10407 if (list == null) {
10408 return cur;
10409 }
10410 int N = list.size();
10411 for (int i=0; i<N; i++) {
10412 Intent intent = list.get(i);
10413 if (filter.match(resolver, intent, true, TAG) >= 0) {
10414 if (cur == null) {
10415 cur = new ArrayList<Intent>();
10416 }
10417 cur.add(intent);
10418 }
10419 }
10420 return cur;
10421 }
10422
10423 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010424 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010425 + mBroadcastsScheduled);
10426
10427 if (mBroadcastsScheduled) {
10428 return;
10429 }
10430 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10431 mBroadcastsScheduled = true;
10432 }
10433
10434 public Intent registerReceiver(IApplicationThread caller,
10435 IIntentReceiver receiver, IntentFilter filter, String permission) {
10436 synchronized(this) {
10437 ProcessRecord callerApp = null;
10438 if (caller != null) {
10439 callerApp = getRecordForAppLocked(caller);
10440 if (callerApp == null) {
10441 throw new SecurityException(
10442 "Unable to find app for caller " + caller
10443 + " (pid=" + Binder.getCallingPid()
10444 + ") when registering receiver " + receiver);
10445 }
10446 }
10447
10448 List allSticky = null;
10449
10450 // Look for any matching sticky broadcasts...
10451 Iterator actions = filter.actionsIterator();
10452 if (actions != null) {
10453 while (actions.hasNext()) {
10454 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010455 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456 }
10457 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010458 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010459 }
10460
10461 // The first sticky in the list is returned directly back to
10462 // the client.
10463 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10464
Joe Onorato8a9b2202010-02-26 18:56:32 -080010465 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010466 + ": " + sticky);
10467
10468 if (receiver == null) {
10469 return sticky;
10470 }
10471
10472 ReceiverList rl
10473 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10474 if (rl == null) {
10475 rl = new ReceiverList(this, callerApp,
10476 Binder.getCallingPid(),
10477 Binder.getCallingUid(), receiver);
10478 if (rl.app != null) {
10479 rl.app.receivers.add(rl);
10480 } else {
10481 try {
10482 receiver.asBinder().linkToDeath(rl, 0);
10483 } catch (RemoteException e) {
10484 return sticky;
10485 }
10486 rl.linkedToDeath = true;
10487 }
10488 mRegisteredReceivers.put(receiver.asBinder(), rl);
10489 }
10490 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10491 rl.add(bf);
10492 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010493 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010494 }
10495 mReceiverResolver.addFilter(bf);
10496
10497 // Enqueue broadcasts for all existing stickies that match
10498 // this filter.
10499 if (allSticky != null) {
10500 ArrayList receivers = new ArrayList();
10501 receivers.add(bf);
10502
10503 int N = allSticky.size();
10504 for (int i=0; i<N; i++) {
10505 Intent intent = (Intent)allSticky.get(i);
10506 BroadcastRecord r = new BroadcastRecord(intent, null,
10507 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010508 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010509 if (mParallelBroadcasts.size() == 0) {
10510 scheduleBroadcastsLocked();
10511 }
10512 mParallelBroadcasts.add(r);
10513 }
10514 }
10515
10516 return sticky;
10517 }
10518 }
10519
10520 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010521 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010522
10523 boolean doNext = false;
10524
10525 synchronized(this) {
10526 ReceiverList rl
10527 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10528 if (rl != null) {
10529 if (rl.curBroadcast != null) {
10530 BroadcastRecord r = rl.curBroadcast;
10531 doNext = finishReceiverLocked(
10532 receiver.asBinder(), r.resultCode, r.resultData,
10533 r.resultExtras, r.resultAbort, true);
10534 }
10535
10536 if (rl.app != null) {
10537 rl.app.receivers.remove(rl);
10538 }
10539 removeReceiverLocked(rl);
10540 if (rl.linkedToDeath) {
10541 rl.linkedToDeath = false;
10542 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10543 }
10544 }
10545 }
10546
10547 if (!doNext) {
10548 return;
10549 }
10550
10551 final long origId = Binder.clearCallingIdentity();
10552 processNextBroadcast(false);
10553 trimApplications();
10554 Binder.restoreCallingIdentity(origId);
10555 }
10556
10557 void removeReceiverLocked(ReceiverList rl) {
10558 mRegisteredReceivers.remove(rl.receiver.asBinder());
10559 int N = rl.size();
10560 for (int i=0; i<N; i++) {
10561 mReceiverResolver.removeFilter(rl.get(i));
10562 }
10563 }
10564
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010565 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10566 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10567 ProcessRecord r = mLruProcesses.get(i);
10568 if (r.thread != null) {
10569 try {
10570 r.thread.dispatchPackageBroadcast(cmd, packages);
10571 } catch (RemoteException ex) {
10572 }
10573 }
10574 }
10575 }
10576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010577 private final int broadcastIntentLocked(ProcessRecord callerApp,
10578 String callerPackage, Intent intent, String resolvedType,
10579 IIntentReceiver resultTo, int resultCode, String resultData,
10580 Bundle map, String requiredPermission,
10581 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10582 intent = new Intent(intent);
10583
Dianne Hackborne7f97212011-02-24 14:40:20 -080010584 // By default broadcasts do not go to stopped apps.
10585 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
10586
Joe Onorato8a9b2202010-02-26 18:56:32 -080010587 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010588 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10589 + " ordered=" + ordered);
10590 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010591 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010592 }
10593
10594 // Handle special intents: if this broadcast is from the package
10595 // manager about a package being removed, we need to remove all of
10596 // its activities from the history stack.
10597 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10598 intent.getAction());
10599 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10600 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010601 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010602 || uidRemoved) {
10603 if (checkComponentPermission(
10604 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010605 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010606 == PackageManager.PERMISSION_GRANTED) {
10607 if (uidRemoved) {
10608 final Bundle intentExtras = intent.getExtras();
10609 final int uid = intentExtras != null
10610 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10611 if (uid >= 0) {
10612 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10613 synchronized (bs) {
10614 bs.removeUidStatsLocked(uid);
10615 }
10616 }
10617 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010618 // If resources are unvailble just force stop all
10619 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010620 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010621 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10622 if (list != null && (list.length > 0)) {
10623 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010624 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010625 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010626 sendPackageBroadcastLocked(
10627 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010628 }
10629 } else {
10630 Uri data = intent.getData();
10631 String ssp;
10632 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10633 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10634 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010635 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010636 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010637 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10638 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10639 new String[] {ssp});
10640 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010641 }
10642 }
10643 }
10644 } else {
10645 String msg = "Permission Denial: " + intent.getAction()
10646 + " broadcast from " + callerPackage + " (pid=" + callingPid
10647 + ", uid=" + callingUid + ")"
10648 + " requires "
10649 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010650 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010651 throw new SecurityException(msg);
10652 }
10653 }
10654
10655 /*
10656 * If this is the time zone changed action, queue up a message that will reset the timezone
10657 * of all currently running processes. This message will get queued up before the broadcast
10658 * happens.
10659 */
10660 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10661 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10662 }
10663
Robert Greenwalt03595d02010-11-02 14:08:23 -070010664 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10665 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10666 }
10667
Robert Greenwalt434203a2010-10-11 16:00:27 -070010668 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10669 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10670 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10671 }
10672
Dianne Hackborn854060af2009-07-09 18:14:31 -070010673 /*
10674 * Prevent non-system code (defined here to be non-persistent
10675 * processes) from sending protected broadcasts.
10676 */
10677 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10678 || callingUid == Process.SHELL_UID || callingUid == 0) {
10679 // Always okay.
10680 } else if (callerApp == null || !callerApp.persistent) {
10681 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010682 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010683 intent.getAction())) {
10684 String msg = "Permission Denial: not allowed to send broadcast "
10685 + intent.getAction() + " from pid="
10686 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010687 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010688 throw new SecurityException(msg);
10689 }
10690 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010691 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010692 return BROADCAST_SUCCESS;
10693 }
10694 }
10695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010696 // Add to the sticky list if requested.
10697 if (sticky) {
10698 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10699 callingPid, callingUid)
10700 != PackageManager.PERMISSION_GRANTED) {
10701 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10702 + callingPid + ", uid=" + callingUid
10703 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010704 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010705 throw new SecurityException(msg);
10706 }
10707 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010708 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010709 + " and enforce permission " + requiredPermission);
10710 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10711 }
10712 if (intent.getComponent() != null) {
10713 throw new SecurityException(
10714 "Sticky broadcasts can't target a specific component");
10715 }
10716 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10717 if (list == null) {
10718 list = new ArrayList<Intent>();
10719 mStickyBroadcasts.put(intent.getAction(), list);
10720 }
10721 int N = list.size();
10722 int i;
10723 for (i=0; i<N; i++) {
10724 if (intent.filterEquals(list.get(i))) {
10725 // This sticky already exists, replace it.
10726 list.set(i, new Intent(intent));
10727 break;
10728 }
10729 }
10730 if (i >= N) {
10731 list.add(new Intent(intent));
10732 }
10733 }
10734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010735 // Figure out who all will receive this broadcast.
10736 List receivers = null;
10737 List<BroadcastFilter> registeredReceivers = null;
10738 try {
10739 if (intent.getComponent() != null) {
10740 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010741 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010742 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010743 if (ai != null) {
10744 receivers = new ArrayList();
10745 ResolveInfo ri = new ResolveInfo();
10746 ri.activityInfo = ai;
10747 receivers.add(ri);
10748 }
10749 } else {
10750 // Need to resolve the intent to interested receivers...
10751 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10752 == 0) {
10753 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010754 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010755 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010756 }
Mihai Preda074edef2009-05-18 17:13:31 +020010757 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010758 }
10759 } catch (RemoteException ex) {
10760 // pm is in same process, this will never happen.
10761 }
10762
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010763 final boolean replacePending =
10764 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10765
Joe Onorato8a9b2202010-02-26 18:56:32 -080010766 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010767 + " replacePending=" + replacePending);
10768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010769 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10770 if (!ordered && NR > 0) {
10771 // If we are not serializing this broadcast, then send the
10772 // registered receivers separately so they don't wait for the
10773 // components to be launched.
10774 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10775 callerPackage, callingPid, callingUid, requiredPermission,
10776 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010777 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010778 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010779 TAG, "Enqueueing parallel broadcast " + r
10780 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010781 boolean replaced = false;
10782 if (replacePending) {
10783 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10784 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010785 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010786 "***** DROPPING PARALLEL: " + intent);
10787 mParallelBroadcasts.set(i, r);
10788 replaced = true;
10789 break;
10790 }
10791 }
10792 }
10793 if (!replaced) {
10794 mParallelBroadcasts.add(r);
10795 scheduleBroadcastsLocked();
10796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010797 registeredReceivers = null;
10798 NR = 0;
10799 }
10800
10801 // Merge into one list.
10802 int ir = 0;
10803 if (receivers != null) {
10804 // A special case for PACKAGE_ADDED: do not allow the package
10805 // being added to see this broadcast. This prevents them from
10806 // using this as a back door to get run as soon as they are
10807 // installed. Maybe in the future we want to have a special install
10808 // broadcast or such for apps, but we'd like to deliberately make
10809 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010810 String skipPackages[] = null;
10811 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10812 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10813 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10814 Uri data = intent.getData();
10815 if (data != null) {
10816 String pkgName = data.getSchemeSpecificPart();
10817 if (pkgName != null) {
10818 skipPackages = new String[] { pkgName };
10819 }
10820 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010821 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010822 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010823 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010824 if (skipPackages != null && (skipPackages.length > 0)) {
10825 for (String skipPackage : skipPackages) {
10826 if (skipPackage != null) {
10827 int NT = receivers.size();
10828 for (int it=0; it<NT; it++) {
10829 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10830 if (curt.activityInfo.packageName.equals(skipPackage)) {
10831 receivers.remove(it);
10832 it--;
10833 NT--;
10834 }
10835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836 }
10837 }
10838 }
10839
10840 int NT = receivers != null ? receivers.size() : 0;
10841 int it = 0;
10842 ResolveInfo curt = null;
10843 BroadcastFilter curr = null;
10844 while (it < NT && ir < NR) {
10845 if (curt == null) {
10846 curt = (ResolveInfo)receivers.get(it);
10847 }
10848 if (curr == null) {
10849 curr = registeredReceivers.get(ir);
10850 }
10851 if (curr.getPriority() >= curt.priority) {
10852 // Insert this broadcast record into the final list.
10853 receivers.add(it, curr);
10854 ir++;
10855 curr = null;
10856 it++;
10857 NT++;
10858 } else {
10859 // Skip to the next ResolveInfo in the final list.
10860 it++;
10861 curt = null;
10862 }
10863 }
10864 }
10865 while (ir < NR) {
10866 if (receivers == null) {
10867 receivers = new ArrayList();
10868 }
10869 receivers.add(registeredReceivers.get(ir));
10870 ir++;
10871 }
10872
10873 if ((receivers != null && receivers.size() > 0)
10874 || resultTo != null) {
10875 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10876 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010877 receivers, resultTo, resultCode, resultData, map, ordered,
10878 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010879 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010880 TAG, "Enqueueing ordered broadcast " + r
10881 + ": prev had " + mOrderedBroadcasts.size());
10882 if (DEBUG_BROADCAST) {
10883 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010884 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010885 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010886 boolean replaced = false;
10887 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010888 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010889 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010890 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010891 "***** DROPPING ORDERED: " + intent);
10892 mOrderedBroadcasts.set(i, r);
10893 replaced = true;
10894 break;
10895 }
10896 }
10897 }
10898 if (!replaced) {
10899 mOrderedBroadcasts.add(r);
10900 scheduleBroadcastsLocked();
10901 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010902 }
10903
10904 return BROADCAST_SUCCESS;
10905 }
10906
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010907 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010908 // Refuse possible leaked file descriptors
10909 if (intent != null && intent.hasFileDescriptors() == true) {
10910 throw new IllegalArgumentException("File descriptors passed in Intent");
10911 }
10912
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010913 int flags = intent.getFlags();
10914
10915 if (!mProcessesReady) {
10916 // if the caller really truly claims to know what they're doing, go
10917 // ahead and allow the broadcast without launching any receivers
10918 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10919 intent = new Intent(intent);
10920 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10921 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10922 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10923 + " before boot completion");
10924 throw new IllegalStateException("Cannot broadcast before boot completed");
10925 }
10926 }
10927
10928 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10929 throw new IllegalArgumentException(
10930 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10931 }
10932
10933 return intent;
10934 }
10935
10936 public final int broadcastIntent(IApplicationThread caller,
10937 Intent intent, String resolvedType, IIntentReceiver resultTo,
10938 int resultCode, String resultData, Bundle map,
10939 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010940 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010941 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010943 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10944 final int callingPid = Binder.getCallingPid();
10945 final int callingUid = Binder.getCallingUid();
10946 final long origId = Binder.clearCallingIdentity();
10947 int res = broadcastIntentLocked(callerApp,
10948 callerApp != null ? callerApp.info.packageName : null,
10949 intent, resolvedType, resultTo,
10950 resultCode, resultData, map, requiredPermission, serialized,
10951 sticky, callingPid, callingUid);
10952 Binder.restoreCallingIdentity(origId);
10953 return res;
10954 }
10955 }
10956
10957 int broadcastIntentInPackage(String packageName, int uid,
10958 Intent intent, String resolvedType, IIntentReceiver resultTo,
10959 int resultCode, String resultData, Bundle map,
10960 String requiredPermission, boolean serialized, boolean sticky) {
10961 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010962 intent = verifyBroadcastLocked(intent);
10963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010964 final long origId = Binder.clearCallingIdentity();
10965 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10966 resultTo, resultCode, resultData, map, requiredPermission,
10967 serialized, sticky, -1, uid);
10968 Binder.restoreCallingIdentity(origId);
10969 return res;
10970 }
10971 }
10972
10973 public final void unbroadcastIntent(IApplicationThread caller,
10974 Intent intent) {
10975 // Refuse possible leaked file descriptors
10976 if (intent != null && intent.hasFileDescriptors() == true) {
10977 throw new IllegalArgumentException("File descriptors passed in Intent");
10978 }
10979
10980 synchronized(this) {
10981 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10982 != PackageManager.PERMISSION_GRANTED) {
10983 String msg = "Permission Denial: unbroadcastIntent() from pid="
10984 + Binder.getCallingPid()
10985 + ", uid=" + Binder.getCallingUid()
10986 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010987 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010988 throw new SecurityException(msg);
10989 }
10990 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10991 if (list != null) {
10992 int N = list.size();
10993 int i;
10994 for (i=0; i<N; i++) {
10995 if (intent.filterEquals(list.get(i))) {
10996 list.remove(i);
10997 break;
10998 }
10999 }
11000 }
11001 }
11002 }
11003
11004 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11005 String resultData, Bundle resultExtras, boolean resultAbort,
11006 boolean explicit) {
11007 if (mOrderedBroadcasts.size() == 0) {
11008 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011009 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011010 }
11011 return false;
11012 }
11013 BroadcastRecord r = mOrderedBroadcasts.get(0);
11014 if (r.receiver == null) {
11015 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011016 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017 }
11018 return false;
11019 }
11020 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011021 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011022 return false;
11023 }
11024 int state = r.state;
11025 r.state = r.IDLE;
11026 if (state == r.IDLE) {
11027 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011028 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029 }
11030 }
11031 r.receiver = null;
11032 r.intent.setComponent(null);
11033 if (r.curApp != null) {
11034 r.curApp.curReceiver = null;
11035 }
11036 if (r.curFilter != null) {
11037 r.curFilter.receiverList.curBroadcast = null;
11038 }
11039 r.curFilter = null;
11040 r.curApp = null;
11041 r.curComponent = null;
11042 r.curReceiver = null;
11043 mPendingBroadcast = null;
11044
11045 r.resultCode = resultCode;
11046 r.resultData = resultData;
11047 r.resultExtras = resultExtras;
11048 r.resultAbort = resultAbort;
11049
11050 // We will process the next receiver right now if this is finishing
11051 // an app receiver (which is always asynchronous) or after we have
11052 // come back from calling a receiver.
11053 return state == BroadcastRecord.APP_RECEIVE
11054 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11055 }
11056
11057 public void finishReceiver(IBinder who, int resultCode, String resultData,
11058 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011059 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011060
11061 // Refuse possible leaked file descriptors
11062 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11063 throw new IllegalArgumentException("File descriptors passed in Bundle");
11064 }
11065
11066 boolean doNext;
11067
11068 final long origId = Binder.clearCallingIdentity();
11069
11070 synchronized(this) {
11071 doNext = finishReceiverLocked(
11072 who, resultCode, resultData, resultExtras, resultAbort, true);
11073 }
11074
11075 if (doNext) {
11076 processNextBroadcast(false);
11077 }
11078 trimApplications();
11079
11080 Binder.restoreCallingIdentity(origId);
11081 }
11082
Jeff Brown4d94a762010-09-23 11:33:28 -070011083 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011084 if (r.nextReceiver > 0) {
11085 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11086 if (curReceiver instanceof BroadcastFilter) {
11087 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011088 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011089 System.identityHashCode(r),
11090 r.intent.getAction(),
11091 r.nextReceiver - 1,
11092 System.identityHashCode(bf));
11093 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011094 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011095 System.identityHashCode(r),
11096 r.intent.getAction(),
11097 r.nextReceiver - 1,
11098 ((ResolveInfo)curReceiver).toString());
11099 }
11100 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011101 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011102 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011103 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 System.identityHashCode(r),
11105 r.intent.getAction(),
11106 r.nextReceiver,
11107 "NONE");
11108 }
11109 }
11110
Jeff Brown4d94a762010-09-23 11:33:28 -070011111 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11112 if (! mPendingBroadcastTimeoutMessage) {
11113 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11114 mHandler.sendMessageAtTime(msg, timeoutTime);
11115 mPendingBroadcastTimeoutMessage = true;
11116 }
11117 }
11118
11119 private final void cancelBroadcastTimeoutLocked() {
11120 if (mPendingBroadcastTimeoutMessage) {
11121 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11122 mPendingBroadcastTimeoutMessage = false;
11123 }
11124 }
11125
11126 private final void broadcastTimeoutLocked(boolean fromMsg) {
11127 if (fromMsg) {
11128 mPendingBroadcastTimeoutMessage = false;
11129 }
11130
11131 if (mOrderedBroadcasts.size() == 0) {
11132 return;
11133 }
11134
11135 long now = SystemClock.uptimeMillis();
11136 BroadcastRecord r = mOrderedBroadcasts.get(0);
11137 if (fromMsg) {
11138 if (mDidDexOpt) {
11139 // Delay timeouts until dexopt finishes.
11140 mDidDexOpt = false;
11141 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11142 setBroadcastTimeoutLocked(timeoutTime);
11143 return;
11144 }
11145 if (! mProcessesReady) {
11146 // Only process broadcast timeouts if the system is ready. That way
11147 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11148 // to do heavy lifting for system up.
11149 return;
11150 }
11151
11152 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11153 if (timeoutTime > now) {
11154 // We can observe premature timeouts because we do not cancel and reset the
11155 // broadcast timeout message after each receiver finishes. Instead, we set up
11156 // an initial timeout then kick it down the road a little further as needed
11157 // when it expires.
11158 if (DEBUG_BROADCAST) Slog.v(TAG,
11159 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11160 + timeoutTime);
11161 setBroadcastTimeoutLocked(timeoutTime);
11162 return;
11163 }
11164 }
11165
11166 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11167 + ", started " + (now - r.receiverTime) + "ms ago");
11168 r.receiverTime = now;
11169 r.anrCount++;
11170
11171 // Current receiver has passed its expiration date.
11172 if (r.nextReceiver <= 0) {
11173 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11174 return;
11175 }
11176
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011177 ProcessRecord app = null;
11178 String anrMessage = null;
11179
Jeff Brown4d94a762010-09-23 11:33:28 -070011180 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11181 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11182 logBroadcastReceiverDiscardLocked(r);
11183 if (curReceiver instanceof BroadcastFilter) {
11184 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11185 if (bf.receiverList.pid != 0
11186 && bf.receiverList.pid != MY_PID) {
11187 synchronized (this.mPidsSelfLocked) {
11188 app = this.mPidsSelfLocked.get(
11189 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011191 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011192 } else {
11193 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011195
Jeff Brown4d94a762010-09-23 11:33:28 -070011196 if (app != null) {
11197 anrMessage = "Broadcast of " + r.intent.toString();
11198 }
11199
11200 if (mPendingBroadcast == r) {
11201 mPendingBroadcast = null;
11202 }
11203
11204 // Move on to the next receiver.
11205 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11206 r.resultExtras, r.resultAbort, true);
11207 scheduleBroadcastsLocked();
11208
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011209 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011210 // Post the ANR to the handler since we do not want to process ANRs while
11211 // potentially holding our lock.
11212 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011213 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 }
11215
11216 private final void processCurBroadcastLocked(BroadcastRecord r,
11217 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011218 if (DEBUG_BROADCAST) Slog.v(TAG,
11219 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 if (app.thread == null) {
11221 throw new RemoteException();
11222 }
11223 r.receiver = app.thread.asBinder();
11224 r.curApp = app;
11225 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011226 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227
11228 // Tell the application to launch this receiver.
11229 r.intent.setComponent(r.curComponent);
11230
11231 boolean started = false;
11232 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011233 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011234 "Delivering to component " + r.curComponent
11235 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011236 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11238 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011239 if (DEBUG_BROADCAST) Slog.v(TAG,
11240 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011241 started = true;
11242 } finally {
11243 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011244 if (DEBUG_BROADCAST) Slog.v(TAG,
11245 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011246 r.receiver = null;
11247 r.curApp = null;
11248 app.curReceiver = null;
11249 }
11250 }
11251
11252 }
11253
Jeff Brown4d94a762010-09-23 11:33:28 -070011254 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011255 Intent intent, int resultCode, String data, Bundle extras,
11256 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011257 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 if (app != null && app.thread != null) {
11259 // If we have an app thread, do the call through that so it is
11260 // correctly ordered with other one-way calls.
11261 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011262 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011264 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011265 }
11266 }
11267
Jeff Brown4d94a762010-09-23 11:33:28 -070011268 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 BroadcastFilter filter, boolean ordered) {
11270 boolean skip = false;
11271 if (filter.requiredPermission != null) {
11272 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011273 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011275 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011276 + r.intent.toString()
11277 + " from " + r.callerPackage + " (pid="
11278 + r.callingPid + ", uid=" + r.callingUid + ")"
11279 + " requires " + filter.requiredPermission
11280 + " due to registered receiver " + filter);
11281 skip = true;
11282 }
11283 }
11284 if (r.requiredPermission != null) {
11285 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011286 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011287 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011288 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011289 + r.intent.toString()
11290 + " to " + filter.receiverList.app
11291 + " (pid=" + filter.receiverList.pid
11292 + ", uid=" + filter.receiverList.uid + ")"
11293 + " requires " + r.requiredPermission
11294 + " due to sender " + r.callerPackage
11295 + " (uid " + r.callingUid + ")");
11296 skip = true;
11297 }
11298 }
11299
11300 if (!skip) {
11301 // If this is not being sent as an ordered broadcast, then we
11302 // don't want to touch the fields that keep track of the current
11303 // state of ordered broadcasts.
11304 if (ordered) {
11305 r.receiver = filter.receiverList.receiver.asBinder();
11306 r.curFilter = filter;
11307 filter.receiverList.curBroadcast = r;
11308 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011309 if (filter.receiverList.app != null) {
11310 // Bump hosting application to no longer be in background
11311 // scheduling class. Note that we can't do that if there
11312 // isn't an app... but we can only be in that case for
11313 // things that directly call the IActivityManager API, which
11314 // are already core system stuff so don't matter for this.
11315 r.curApp = filter.receiverList.app;
11316 filter.receiverList.app.curReceiver = r;
11317 updateOomAdjLocked();
11318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011319 }
11320 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011321 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011322 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011323 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011324 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011325 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011326 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011327 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011328 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 if (ordered) {
11330 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11331 }
11332 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011333 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334 if (ordered) {
11335 r.receiver = null;
11336 r.curFilter = null;
11337 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011338 if (filter.receiverList.app != null) {
11339 filter.receiverList.app.curReceiver = null;
11340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 }
11342 }
11343 }
11344 }
11345
Dianne Hackborn12527f92009-11-11 17:39:50 -080011346 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11347 if (r.callingUid < 0) {
11348 // This was from a registerReceiver() call; ignore it.
11349 return;
11350 }
11351 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11352 MAX_BROADCAST_HISTORY-1);
11353 r.finishTime = SystemClock.uptimeMillis();
11354 mBroadcastHistory[0] = r;
11355 }
11356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 private final void processNextBroadcast(boolean fromMsg) {
11358 synchronized(this) {
11359 BroadcastRecord r;
11360
Joe Onorato8a9b2202010-02-26 18:56:32 -080011361 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011363 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011364
11365 updateCpuStats();
11366
11367 if (fromMsg) {
11368 mBroadcastsScheduled = false;
11369 }
11370
11371 // First, deliver any non-serialized broadcasts right away.
11372 while (mParallelBroadcasts.size() > 0) {
11373 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011374 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011375 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011376 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011377 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011378 for (int i=0; i<N; i++) {
11379 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011380 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011381 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011382 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011383 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011384 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011385 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011386 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011387 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011388 }
11389
11390 // Now take care of the next serialized one...
11391
11392 // If we are waiting for a process to come up to handle the next
11393 // broadcast, then do nothing at this point. Just in case, we
11394 // check that the process we're waiting for still exists.
11395 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011396 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011397 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011398 + mPendingBroadcast.curApp);
11399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011400
11401 boolean isDead;
11402 synchronized (mPidsSelfLocked) {
11403 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11404 }
11405 if (!isDead) {
11406 // It's still alive, so keep waiting
11407 return;
11408 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011409 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011410 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011411 mPendingBroadcast.state = BroadcastRecord.IDLE;
11412 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011413 mPendingBroadcast = null;
11414 }
11415 }
11416
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011417 boolean looped = false;
11418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011419 do {
11420 if (mOrderedBroadcasts.size() == 0) {
11421 // No more broadcasts pending, so all done!
11422 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011423 if (looped) {
11424 // If we had finished the last ordered broadcast, then
11425 // make sure all processes have correct oom and sched
11426 // adjustments.
11427 updateOomAdjLocked();
11428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011429 return;
11430 }
11431 r = mOrderedBroadcasts.get(0);
11432 boolean forceReceive = false;
11433
11434 // Ensure that even if something goes awry with the timeout
11435 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011436 // and continue to make progress.
11437 //
11438 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011439 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011440 // one time heavy lifting after system upgrades and can take
11441 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011442 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011443 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011444 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011445 if ((numReceivers > 0) &&
11446 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011447 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011448 + " now=" + now
11449 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011450 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011451 + " intent=" + r.intent
11452 + " numReceivers=" + numReceivers
11453 + " nextReceiver=" + r.nextReceiver
11454 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011455 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011456 forceReceive = true;
11457 r.state = BroadcastRecord.IDLE;
11458 }
11459 }
11460
11461 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011462 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011463 "processNextBroadcast() called when not idle (state="
11464 + r.state + ")");
11465 return;
11466 }
11467
11468 if (r.receivers == null || r.nextReceiver >= numReceivers
11469 || r.resultAbort || forceReceive) {
11470 // No more receivers for this broadcast! Send the final
11471 // result if requested...
11472 if (r.resultTo != null) {
11473 try {
11474 if (DEBUG_BROADCAST) {
11475 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011476 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011477 + " seq=" + seq + " app=" + r.callerApp);
11478 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011479 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011480 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011481 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011482 // Set this to null so that the reference
11483 // (local and remote) isnt kept in the mBroadcastHistory.
11484 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011486 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011487 }
11488 }
11489
Joe Onorato8a9b2202010-02-26 18:56:32 -080011490 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011491 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011492
Joe Onorato8a9b2202010-02-26 18:56:32 -080011493 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011494 + r);
11495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011496 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011497 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011498 mOrderedBroadcasts.remove(0);
11499 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011500 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011501 continue;
11502 }
11503 } while (r == null);
11504
11505 // Get the next receiver...
11506 int recIdx = r.nextReceiver++;
11507
11508 // Keep track of when this receiver started, and make sure there
11509 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011510 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011512 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513
Joe Onorato8a9b2202010-02-26 18:56:32 -080011514 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011515 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011516 }
11517 if (! mPendingBroadcastTimeoutMessage) {
11518 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011519 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011520 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11521 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011522 }
11523
11524 Object nextReceiver = r.receivers.get(recIdx);
11525 if (nextReceiver instanceof BroadcastFilter) {
11526 // Simple case: this is a registered receiver who gets
11527 // a direct call.
11528 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011529 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011530 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011531 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011532 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011533 if (r.receiver == null || !r.ordered) {
11534 // The receiver has already finished, so schedule to
11535 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011536 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11537 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011538 r.state = BroadcastRecord.IDLE;
11539 scheduleBroadcastsLocked();
11540 }
11541 return;
11542 }
11543
11544 // Hard case: need to instantiate the receiver, possibly
11545 // starting its application process to host it.
11546
11547 ResolveInfo info =
11548 (ResolveInfo)nextReceiver;
11549
11550 boolean skip = false;
11551 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011552 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
11553 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011554 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011555 if (!info.activityInfo.exported) {
11556 Slog.w(TAG, "Permission Denial: broadcasting "
11557 + r.intent.toString()
11558 + " from " + r.callerPackage + " (pid=" + r.callingPid
11559 + ", uid=" + r.callingUid + ")"
11560 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
11561 + " due to receiver " + info.activityInfo.packageName
11562 + "/" + info.activityInfo.name);
11563 } else {
11564 Slog.w(TAG, "Permission Denial: broadcasting "
11565 + r.intent.toString()
11566 + " from " + r.callerPackage + " (pid=" + r.callingPid
11567 + ", uid=" + r.callingUid + ")"
11568 + " requires " + info.activityInfo.permission
11569 + " due to receiver " + info.activityInfo.packageName
11570 + "/" + info.activityInfo.name);
11571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572 skip = true;
11573 }
11574 if (r.callingUid != Process.SYSTEM_UID &&
11575 r.requiredPermission != null) {
11576 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011577 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 checkPermission(r.requiredPermission,
11579 info.activityInfo.applicationInfo.packageName);
11580 } catch (RemoteException e) {
11581 perm = PackageManager.PERMISSION_DENIED;
11582 }
11583 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011584 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011585 + r.intent + " to "
11586 + info.activityInfo.applicationInfo.packageName
11587 + " requires " + r.requiredPermission
11588 + " due to sender " + r.callerPackage
11589 + " (uid " + r.callingUid + ")");
11590 skip = true;
11591 }
11592 }
11593 if (r.curApp != null && r.curApp.crashing) {
11594 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011595 if (DEBUG_BROADCAST) Slog.v(TAG,
11596 "Skipping deliver ordered " + r + " to " + r.curApp
11597 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 skip = true;
11599 }
11600
11601 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011602 if (DEBUG_BROADCAST) Slog.v(TAG,
11603 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604 r.receiver = null;
11605 r.curFilter = null;
11606 r.state = BroadcastRecord.IDLE;
11607 scheduleBroadcastsLocked();
11608 return;
11609 }
11610
11611 r.state = BroadcastRecord.APP_RECEIVE;
11612 String targetProcess = info.activityInfo.processName;
11613 r.curComponent = new ComponentName(
11614 info.activityInfo.applicationInfo.packageName,
11615 info.activityInfo.name);
11616 r.curReceiver = info.activityInfo;
11617
Dianne Hackborne7f97212011-02-24 14:40:20 -080011618 // Broadcast is being executed, its package can't be stopped.
11619 try {
11620 AppGlobals.getPackageManager().setPackageStoppedState(
11621 r.curComponent.getPackageName(), false);
11622 } catch (RemoteException e) {
11623 }
11624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011625 // Is this receiver's application already running?
11626 ProcessRecord app = getProcessRecordLocked(targetProcess,
11627 info.activityInfo.applicationInfo.uid);
11628 if (app != null && app.thread != null) {
11629 try {
11630 processCurBroadcastLocked(r, app);
11631 return;
11632 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011633 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011634 + r.curComponent, e);
11635 }
11636
11637 // If a dead object exception was thrown -- fall through to
11638 // restart the application.
11639 }
11640
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011641 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011642 if (DEBUG_BROADCAST) Slog.v(TAG,
11643 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011644 if ((r.curApp=startProcessLocked(targetProcess,
11645 info.activityInfo.applicationInfo, true,
11646 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011647 "broadcast", r.curComponent,
11648 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11649 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011650 // Ah, this recipient is unavailable. Finish it if necessary,
11651 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011652 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011653 + info.activityInfo.applicationInfo.packageName + "/"
11654 + info.activityInfo.applicationInfo.uid + " for broadcast "
11655 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011656 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011657 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11658 r.resultExtras, r.resultAbort, true);
11659 scheduleBroadcastsLocked();
11660 r.state = BroadcastRecord.IDLE;
11661 return;
11662 }
11663
11664 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011665 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666 }
11667 }
11668
11669 // =========================================================
11670 // INSTRUMENTATION
11671 // =========================================================
11672
11673 public boolean startInstrumentation(ComponentName className,
11674 String profileFile, int flags, Bundle arguments,
11675 IInstrumentationWatcher watcher) {
11676 // Refuse possible leaked file descriptors
11677 if (arguments != null && arguments.hasFileDescriptors()) {
11678 throw new IllegalArgumentException("File descriptors passed in Bundle");
11679 }
11680
11681 synchronized(this) {
11682 InstrumentationInfo ii = null;
11683 ApplicationInfo ai = null;
11684 try {
11685 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011686 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011687 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011688 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011689 } catch (PackageManager.NameNotFoundException e) {
11690 }
11691 if (ii == null) {
11692 reportStartInstrumentationFailure(watcher, className,
11693 "Unable to find instrumentation info for: " + className);
11694 return false;
11695 }
11696 if (ai == null) {
11697 reportStartInstrumentationFailure(watcher, className,
11698 "Unable to find instrumentation target package: " + ii.targetPackage);
11699 return false;
11700 }
11701
11702 int match = mContext.getPackageManager().checkSignatures(
11703 ii.targetPackage, ii.packageName);
11704 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11705 String msg = "Permission Denial: starting instrumentation "
11706 + className + " from pid="
11707 + Binder.getCallingPid()
11708 + ", uid=" + Binder.getCallingPid()
11709 + " not allowed because package " + ii.packageName
11710 + " does not have a signature matching the target "
11711 + ii.targetPackage;
11712 reportStartInstrumentationFailure(watcher, className, msg);
11713 throw new SecurityException(msg);
11714 }
11715
11716 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011717 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011718 ProcessRecord app = addAppLocked(ai);
11719 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011720 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011721 app.instrumentationProfileFile = profileFile;
11722 app.instrumentationArguments = arguments;
11723 app.instrumentationWatcher = watcher;
11724 app.instrumentationResultClass = className;
11725 Binder.restoreCallingIdentity(origId);
11726 }
11727
11728 return true;
11729 }
11730
11731 /**
11732 * Report errors that occur while attempting to start Instrumentation. Always writes the
11733 * error to the logs, but if somebody is watching, send the report there too. This enables
11734 * the "am" command to report errors with more information.
11735 *
11736 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11737 * @param cn The component name of the instrumentation.
11738 * @param report The error report.
11739 */
11740 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11741 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011742 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011743 try {
11744 if (watcher != null) {
11745 Bundle results = new Bundle();
11746 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11747 results.putString("Error", report);
11748 watcher.instrumentationStatus(cn, -1, results);
11749 }
11750 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011751 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011752 }
11753 }
11754
11755 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11756 if (app.instrumentationWatcher != null) {
11757 try {
11758 // NOTE: IInstrumentationWatcher *must* be oneway here
11759 app.instrumentationWatcher.instrumentationFinished(
11760 app.instrumentationClass,
11761 resultCode,
11762 results);
11763 } catch (RemoteException e) {
11764 }
11765 }
11766 app.instrumentationWatcher = null;
11767 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011768 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011769 app.instrumentationProfileFile = null;
11770 app.instrumentationArguments = null;
11771
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011772 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011773 }
11774
11775 public void finishInstrumentation(IApplicationThread target,
11776 int resultCode, Bundle results) {
11777 // Refuse possible leaked file descriptors
11778 if (results != null && results.hasFileDescriptors()) {
11779 throw new IllegalArgumentException("File descriptors passed in Intent");
11780 }
11781
11782 synchronized(this) {
11783 ProcessRecord app = getRecordForAppLocked(target);
11784 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011785 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011786 return;
11787 }
11788 final long origId = Binder.clearCallingIdentity();
11789 finishInstrumentationLocked(app, resultCode, results);
11790 Binder.restoreCallingIdentity(origId);
11791 }
11792 }
11793
11794 // =========================================================
11795 // CONFIGURATION
11796 // =========================================================
11797
11798 public ConfigurationInfo getDeviceConfigurationInfo() {
11799 ConfigurationInfo config = new ConfigurationInfo();
11800 synchronized (this) {
11801 config.reqTouchScreen = mConfiguration.touchscreen;
11802 config.reqKeyboardType = mConfiguration.keyboard;
11803 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011804 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11805 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011806 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11807 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011808 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11809 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011810 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11811 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011812 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011813 }
11814 return config;
11815 }
11816
11817 public Configuration getConfiguration() {
11818 Configuration ci;
11819 synchronized(this) {
11820 ci = new Configuration(mConfiguration);
11821 }
11822 return ci;
11823 }
11824
11825 public void updateConfiguration(Configuration values) {
11826 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11827 "updateConfiguration()");
11828
11829 synchronized(this) {
11830 if (values == null && mWindowManager != null) {
11831 // sentinel: fetch the current configuration from the window manager
11832 values = mWindowManager.computeNewConfiguration();
11833 }
11834
11835 final long origId = Binder.clearCallingIdentity();
11836 updateConfigurationLocked(values, null);
11837 Binder.restoreCallingIdentity(origId);
11838 }
11839 }
11840
11841 /**
11842 * Do either or both things: (1) change the current configuration, and (2)
11843 * make sure the given activity is running with the (now) current
11844 * configuration. Returns true if the activity has been left running, or
11845 * false if <var>starting</var> is being destroyed to match the new
11846 * configuration.
11847 */
11848 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011849 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011850 int changes = 0;
11851
11852 boolean kept = true;
11853
11854 if (values != null) {
11855 Configuration newConfig = new Configuration(mConfiguration);
11856 changes = newConfig.updateFrom(values);
11857 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011858 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011859 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011860 }
11861
Doug Zongker2bec3d42009-12-04 12:52:44 -080011862 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011863
11864 if (values.locale != null) {
11865 saveLocaleLocked(values.locale,
11866 !values.locale.equals(mConfiguration.locale),
11867 values.userSetLocale);
11868 }
11869
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011870 mConfigurationSeq++;
11871 if (mConfigurationSeq <= 0) {
11872 mConfigurationSeq = 1;
11873 }
11874 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011875 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011876 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011877
11878 AttributeCache ac = AttributeCache.instance();
11879 if (ac != null) {
11880 ac.updateConfiguration(mConfiguration);
11881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011882
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011883 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11884 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11885 msg.obj = new Configuration(mConfiguration);
11886 mHandler.sendMessage(msg);
11887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011888
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011889 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11890 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011891 try {
11892 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011893 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011894 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011895 app.thread.scheduleConfigurationChanged(mConfiguration);
11896 }
11897 } catch (Exception e) {
11898 }
11899 }
11900 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011901 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11902 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11904 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011905 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11906 broadcastIntentLocked(null, null,
11907 new Intent(Intent.ACTION_LOCALE_CHANGED),
11908 null, null, 0, null, null,
11909 null, false, false, MY_PID, Process.SYSTEM_UID);
11910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011911 }
11912 }
11913
11914 if (changes != 0 && starting == null) {
11915 // If the configuration changed, and the caller is not already
11916 // in the process of starting an activity, then find the top
11917 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011918 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011919 }
11920
11921 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011922 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080011923 // And we need to make sure at this point that all other activities
11924 // are made visible with the correct configuration.
11925 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011926 }
11927
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011928 if (values != null && mWindowManager != null) {
11929 mWindowManager.setNewConfiguration(mConfiguration);
11930 }
11931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011932 return kept;
11933 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011934
11935 /**
11936 * Save the locale. You must be inside a synchronized (this) block.
11937 */
11938 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11939 if(isDiff) {
11940 SystemProperties.set("user.language", l.getLanguage());
11941 SystemProperties.set("user.region", l.getCountry());
11942 }
11943
11944 if(isPersist) {
11945 SystemProperties.set("persist.sys.language", l.getLanguage());
11946 SystemProperties.set("persist.sys.country", l.getCountry());
11947 SystemProperties.set("persist.sys.localevar", l.getVariant());
11948 }
11949 }
11950
11951 // =========================================================
11952 // LIFETIME MANAGEMENT
11953 // =========================================================
11954
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011955 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11956 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011957 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011958 // This adjustment has already been computed. If we are calling
11959 // from the top, we may have already computed our adjustment with
11960 // an earlier hidden adjustment that isn't really for us... if
11961 // so, use the new hidden adjustment.
11962 if (!recursed && app.hidden) {
11963 app.curAdj = hiddenAdj;
11964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011965 return app.curAdj;
11966 }
11967
11968 if (app.thread == null) {
11969 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011970 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011971 return (app.curAdj=EMPTY_APP_ADJ);
11972 }
11973
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011974 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11975 // The max adjustment doesn't allow this app to be anything
11976 // below foreground, so it is not worth doing work for it.
11977 app.adjType = "fixed";
11978 app.adjSeq = mAdjSeq;
11979 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011980 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011981 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11982 return (app.curAdj=app.maxAdj);
11983 }
11984
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011985 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011986 app.adjSource = null;
11987 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011988 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011989 app.empty = false;
11990 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011991
The Android Open Source Project4df24232009-03-05 14:34:35 -080011992 // Determine the importance of the process, starting with most
11993 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011994 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011995 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011996 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011997 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011998 // The last app on the list is the foreground app.
11999 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012000 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012001 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012002 } else if (app.instrumentationClass != null) {
12003 // Don't want to kill running instrumentation.
12004 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012005 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012006 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012007 } else if (app.curReceiver != null ||
12008 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12009 // An app that is currently receiving a broadcast also
12010 // counts as being in the foreground.
12011 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012012 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012013 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012014 } else if (app.executingServices.size() > 0) {
12015 // An app that is currently executing a service callback also
12016 // counts as being in the foreground.
12017 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012018 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012019 app.adjType = "exec-service";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012020 } else if ((N=app.activities.size()) != 0) {
12021 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012022 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012023 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012024 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012025 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012026 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012027 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012028 ActivityRecord r = app.activities.get(j);
12029 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012030 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012031 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012032 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012033 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012034 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012035 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012036 } else if (r.state == ActivityState.PAUSING
12037 || r.state == ActivityState.PAUSED
12038 || r.state == ActivityState.STOPPING) {
12039 adj = PERCEPTIBLE_APP_ADJ;
12040 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012041 }
12042 }
12043 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012044 // A very not-needed process. If this is lower in the lru list,
12045 // we will push it in to the empty bucket.
12046 app.hidden = true;
12047 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012048 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012049 adj = hiddenAdj;
12050 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012051 }
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012052
12053 if (adj > PERCEPTIBLE_APP_ADJ) {
12054 if (app.foregroundServices) {
12055 // The user is aware of this app, so make it visible.
12056 adj = PERCEPTIBLE_APP_ADJ;
12057 schedGroup = Process.THREAD_GROUP_DEFAULT;
12058 app.adjType = "foreground-service";
12059 } else if (app.forcingToForeground != null) {
12060 // The user is aware of this app, so make it visible.
12061 adj = PERCEPTIBLE_APP_ADJ;
12062 schedGroup = Process.THREAD_GROUP_DEFAULT;
12063 app.adjType = "force-foreground";
12064 app.adjSource = app.forcingToForeground;
12065 }
12066 }
12067
12068 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12069 // We don't want to kill the current heavy-weight process.
12070 adj = HEAVY_WEIGHT_APP_ADJ;
12071 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12072 app.adjType = "heavy";
12073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012074
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012075 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12076 // This process is hosting what we currently consider to be the
12077 // home app, so we don't want to let it go into the background.
12078 adj = HOME_APP_ADJ;
12079 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12080 app.adjType = "home";
12081 }
12082
Joe Onorato8a9b2202010-02-26 18:56:32 -080012083 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012084
The Android Open Source Project4df24232009-03-05 14:34:35 -080012085 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012086 // there are applications dependent on our services or providers, but
12087 // this gives us a baseline and makes sure we don't get into an
12088 // infinite recursion.
12089 app.adjSeq = mAdjSeq;
12090 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012091
Christopher Tate6fa95972009-06-05 18:43:55 -070012092 if (mBackupTarget != null && app == mBackupTarget.app) {
12093 // If possible we want to avoid killing apps while they're being backed up
12094 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012095 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012096 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012097 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012098 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012099 }
12100 }
12101
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012102 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12103 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012104 final long now = SystemClock.uptimeMillis();
12105 // This process is more important if the top activity is
12106 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012107 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012108 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012109 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012110 if (s.startRequested) {
12111 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12112 // This service has seen some activity within
12113 // recent memory, so we will keep its process ahead
12114 // of the background processes.
12115 if (adj > SECONDARY_SERVER_ADJ) {
12116 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012117 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012118 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012119 }
12120 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012121 // If we have let the service slide into the background
12122 // state, still have some text describing what it is doing
12123 // even though the service no longer has an impact.
12124 if (adj > SECONDARY_SERVER_ADJ) {
12125 app.adjType = "started-bg-services";
12126 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012127 // Don't kill this process because it is doing work; it
12128 // has said it is doing work.
12129 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012130 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012131 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12132 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012133 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012134 = s.connections.values().iterator();
12135 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012136 ArrayList<ConnectionRecord> clist = kt.next();
12137 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12138 // XXX should compute this based on the max of
12139 // all connected clients.
12140 ConnectionRecord cr = clist.get(i);
12141 if (cr.binding.client == app) {
12142 // Binding to ourself is not interesting.
12143 continue;
12144 }
12145 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12146 ProcessRecord client = cr.binding.client;
12147 int myHiddenAdj = hiddenAdj;
12148 if (myHiddenAdj > client.hiddenAdj) {
12149 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12150 myHiddenAdj = client.hiddenAdj;
12151 } else {
12152 myHiddenAdj = VISIBLE_APP_ADJ;
12153 }
12154 }
12155 int clientAdj = computeOomAdjLocked(
12156 client, myHiddenAdj, TOP_APP, true);
12157 if (adj > clientAdj) {
12158 adj = clientAdj >= VISIBLE_APP_ADJ
12159 ? clientAdj : VISIBLE_APP_ADJ;
12160 if (!client.hidden) {
12161 app.hidden = false;
12162 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012163 if (client.keeping) {
12164 app.keeping = true;
12165 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012166 app.adjType = "service";
12167 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12168 .REASON_SERVICE_IN_USE;
12169 app.adjSource = cr.binding.client;
12170 app.adjTarget = s.name;
12171 }
12172 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12173 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12174 schedGroup = Process.THREAD_GROUP_DEFAULT;
12175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012176 }
12177 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012178 ActivityRecord a = cr.activity;
12179 //if (a != null) {
12180 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12181 //}
12182 if (a != null && adj > FOREGROUND_APP_ADJ &&
12183 (a.state == ActivityState.RESUMED
12184 || a.state == ActivityState.PAUSING)) {
12185 adj = FOREGROUND_APP_ADJ;
12186 schedGroup = Process.THREAD_GROUP_DEFAULT;
12187 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012188 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012189 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12190 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012191 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012192 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012194 }
12195 }
12196 }
12197 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012198
Dianne Hackborn287952c2010-09-22 22:34:31 -070012199 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012200 // would like to avoid killing it unless it would prevent the current
12201 // application from running. By default we put the process in
12202 // with the rest of the background processes; as we scan through
12203 // its services we may bump it up from there.
12204 if (adj > hiddenAdj) {
12205 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012206 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012207 app.adjType = "bg-services";
12208 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012209 }
12210
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012211 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12212 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012213 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012214 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12215 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012216 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012217 if (cpr.clients.size() != 0) {
12218 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12219 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12220 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012221 if (client == app) {
12222 // Being our own client is not interesting.
12223 continue;
12224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012225 int myHiddenAdj = hiddenAdj;
12226 if (myHiddenAdj > client.hiddenAdj) {
12227 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12228 myHiddenAdj = client.hiddenAdj;
12229 } else {
12230 myHiddenAdj = FOREGROUND_APP_ADJ;
12231 }
12232 }
12233 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012234 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012235 if (adj > clientAdj) {
12236 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012237 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012238 if (!client.hidden) {
12239 app.hidden = false;
12240 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012241 if (client.keeping) {
12242 app.keeping = true;
12243 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012244 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012245 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12246 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012247 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012248 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012249 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012250 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12251 schedGroup = Process.THREAD_GROUP_DEFAULT;
12252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012253 }
12254 }
12255 // If the provider has external (non-framework) process
12256 // dependencies, ensure that its adjustment is at least
12257 // FOREGROUND_APP_ADJ.
12258 if (cpr.externals != 0) {
12259 if (adj > FOREGROUND_APP_ADJ) {
12260 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012261 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012262 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012263 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012264 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012265 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012266 }
12267 }
12268 }
12269 }
12270
12271 app.curRawAdj = adj;
12272
Joe Onorato8a9b2202010-02-26 18:56:32 -080012273 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012274 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12275 if (adj > app.maxAdj) {
12276 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012277 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012278 schedGroup = Process.THREAD_GROUP_DEFAULT;
12279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012280 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012281 if (adj < HIDDEN_APP_MIN_ADJ) {
12282 app.keeping = true;
12283 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012284
12285 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012286 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012288 return adj;
12289 }
12290
12291 /**
12292 * Ask a given process to GC right now.
12293 */
12294 final void performAppGcLocked(ProcessRecord app) {
12295 try {
12296 app.lastRequestedGc = SystemClock.uptimeMillis();
12297 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012298 if (app.reportLowMemory) {
12299 app.reportLowMemory = false;
12300 app.thread.scheduleLowMemory();
12301 } else {
12302 app.thread.processInBackground();
12303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012304 }
12305 } catch (Exception e) {
12306 // whatever.
12307 }
12308 }
12309
12310 /**
12311 * Returns true if things are idle enough to perform GCs.
12312 */
Josh Bartel7f208742010-02-25 11:01:44 -060012313 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012314 return mParallelBroadcasts.size() == 0
12315 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012316 && (mSleeping || (mMainStack.mResumedActivity != null &&
12317 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012318 }
12319
12320 /**
12321 * Perform GCs on all processes that are waiting for it, but only
12322 * if things are idle.
12323 */
12324 final void performAppGcsLocked() {
12325 final int N = mProcessesToGc.size();
12326 if (N <= 0) {
12327 return;
12328 }
Josh Bartel7f208742010-02-25 11:01:44 -060012329 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012330 while (mProcessesToGc.size() > 0) {
12331 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012332 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012333 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12334 <= SystemClock.uptimeMillis()) {
12335 // To avoid spamming the system, we will GC processes one
12336 // at a time, waiting a few seconds between each.
12337 performAppGcLocked(proc);
12338 scheduleAppGcsLocked();
12339 return;
12340 } else {
12341 // It hasn't been long enough since we last GCed this
12342 // process... put it in the list to wait for its time.
12343 addProcessToGcListLocked(proc);
12344 break;
12345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012346 }
12347 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012348
12349 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012350 }
12351 }
12352
12353 /**
12354 * If all looks good, perform GCs on all processes waiting for them.
12355 */
12356 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012357 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012358 performAppGcsLocked();
12359 return;
12360 }
12361 // Still not idle, wait some more.
12362 scheduleAppGcsLocked();
12363 }
12364
12365 /**
12366 * Schedule the execution of all pending app GCs.
12367 */
12368 final void scheduleAppGcsLocked() {
12369 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012370
12371 if (mProcessesToGc.size() > 0) {
12372 // Schedule a GC for the time to the next process.
12373 ProcessRecord proc = mProcessesToGc.get(0);
12374 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12375
12376 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12377 long now = SystemClock.uptimeMillis();
12378 if (when < (now+GC_TIMEOUT)) {
12379 when = now + GC_TIMEOUT;
12380 }
12381 mHandler.sendMessageAtTime(msg, when);
12382 }
12383 }
12384
12385 /**
12386 * Add a process to the array of processes waiting to be GCed. Keeps the
12387 * list in sorted order by the last GC time. The process can't already be
12388 * on the list.
12389 */
12390 final void addProcessToGcListLocked(ProcessRecord proc) {
12391 boolean added = false;
12392 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12393 if (mProcessesToGc.get(i).lastRequestedGc <
12394 proc.lastRequestedGc) {
12395 added = true;
12396 mProcessesToGc.add(i+1, proc);
12397 break;
12398 }
12399 }
12400 if (!added) {
12401 mProcessesToGc.add(0, proc);
12402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012403 }
12404
12405 /**
12406 * Set up to ask a process to GC itself. This will either do it
12407 * immediately, or put it on the list of processes to gc the next
12408 * time things are idle.
12409 */
12410 final void scheduleAppGcLocked(ProcessRecord app) {
12411 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012412 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012413 return;
12414 }
12415 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012416 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012417 scheduleAppGcsLocked();
12418 }
12419 }
12420
Dianne Hackborn287952c2010-09-22 22:34:31 -070012421 final void checkExcessivePowerUsageLocked(boolean doKills) {
12422 updateCpuStatsNow();
12423
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012424 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012425 boolean doWakeKills = doKills;
12426 boolean doCpuKills = doKills;
12427 if (mLastPowerCheckRealtime == 0) {
12428 doWakeKills = false;
12429 }
12430 if (mLastPowerCheckUptime == 0) {
12431 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012432 }
12433 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012434 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012435 }
12436 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012437 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12438 final long curUptime = SystemClock.uptimeMillis();
12439 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12440 mLastPowerCheckRealtime = curRealtime;
12441 mLastPowerCheckUptime = curUptime;
12442 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12443 doWakeKills = false;
12444 }
12445 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12446 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012447 }
12448 int i = mLruProcesses.size();
12449 while (i > 0) {
12450 i--;
12451 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012452 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012453 long wtime;
12454 synchronized (stats) {
12455 wtime = stats.getProcessWakeTime(app.info.uid,
12456 app.pid, curRealtime);
12457 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012458 long wtimeUsed = wtime - app.lastWakeTime;
12459 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12460 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012461 StringBuilder sb = new StringBuilder(128);
12462 sb.append("Wake for ");
12463 app.toShortString(sb);
12464 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012465 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012466 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012467 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012468 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012469 sb.append((wtimeUsed*100)/realtimeSince);
12470 sb.append("%)");
12471 Slog.i(TAG, sb.toString());
12472 sb.setLength(0);
12473 sb.append("CPU for ");
12474 app.toShortString(sb);
12475 sb.append(": over ");
12476 TimeUtils.formatDuration(uptimeSince, sb);
12477 sb.append(" used ");
12478 TimeUtils.formatDuration(cputimeUsed, sb);
12479 sb.append(" (");
12480 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012481 sb.append("%)");
12482 Slog.i(TAG, sb.toString());
12483 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012484 // If a process has held a wake lock for more
12485 // than 50% of the time during this period,
12486 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012487 if (doWakeKills && realtimeSince > 0
12488 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12489 synchronized (stats) {
12490 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12491 realtimeSince, wtimeUsed);
12492 }
12493 Slog.w(TAG, "Excessive wake lock in " + app.processName
12494 + " (pid " + app.pid + "): held " + wtimeUsed
12495 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012496 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12497 app.processName, app.setAdj, "excessive wake lock");
12498 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012499 } else if (doCpuKills && uptimeSince > 0
12500 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12501 synchronized (stats) {
12502 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12503 uptimeSince, cputimeUsed);
12504 }
12505 Slog.w(TAG, "Excessive CPU in " + app.processName
12506 + " (pid " + app.pid + "): used " + cputimeUsed
12507 + " during " + uptimeSince);
12508 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12509 app.processName, app.setAdj, "excessive cpu");
12510 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012511 } else {
12512 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012513 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012514 }
12515 }
12516 }
12517 }
12518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012519 private final boolean updateOomAdjLocked(
12520 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12521 app.hiddenAdj = hiddenAdj;
12522
12523 if (app.thread == null) {
12524 return true;
12525 }
12526
Dianne Hackborn287952c2010-09-22 22:34:31 -070012527 final boolean wasKeeping = app.keeping;
12528
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012529 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012530
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012531 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012532 if (app.curRawAdj != app.setRawAdj) {
12533 if (app.curRawAdj > FOREGROUND_APP_ADJ
12534 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12535 // If this app is transitioning from foreground to
12536 // non-foreground, have it do a gc.
12537 scheduleAppGcLocked(app);
12538 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12539 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12540 // Likewise do a gc when an app is moving in to the
12541 // background (such as a service stopping).
12542 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012543 }
12544
12545 if (wasKeeping && !app.keeping) {
12546 // This app is no longer something we want to keep. Note
12547 // its current wake lock time to later know to kill it if
12548 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012549 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12550 synchronized (stats) {
12551 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12552 app.pid, SystemClock.elapsedRealtime());
12553 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012554 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012555 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012557 app.setRawAdj = app.curRawAdj;
12558 }
12559 if (adj != app.setAdj) {
12560 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012561 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012562 TAG, "Set app " + app.processName +
12563 " oom adj to " + adj);
12564 app.setAdj = adj;
12565 } else {
12566 return false;
12567 }
12568 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012569 if (app.setSchedGroup != app.curSchedGroup) {
12570 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012571 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012572 "Setting process group of " + app.processName
12573 + " to " + app.curSchedGroup);
12574 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012575 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012576 try {
12577 Process.setProcessGroup(app.pid, app.curSchedGroup);
12578 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012579 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012580 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012581 e.printStackTrace();
12582 } finally {
12583 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012584 }
12585 }
12586 if (false) {
12587 if (app.thread != null) {
12588 try {
12589 app.thread.setSchedulingGroup(app.curSchedGroup);
12590 } catch (RemoteException e) {
12591 }
12592 }
12593 }
12594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012595 }
12596
12597 return true;
12598 }
12599
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012600 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012601 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012602 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012603 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012604 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012605 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012606 }
12607 }
12608 return resumedActivity;
12609 }
12610
12611 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012612 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012613 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12614 int curAdj = app.curAdj;
12615 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12616 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12617
12618 mAdjSeq++;
12619
12620 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12621 if (res) {
12622 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12623 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12624 if (nowHidden != wasHidden) {
12625 // Changed to/from hidden state, so apps after it in the LRU
12626 // list may also be changed.
12627 updateOomAdjLocked();
12628 }
12629 }
12630 return res;
12631 }
12632
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012633 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012634 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012635 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012636 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12637
12638 if (false) {
12639 RuntimeException e = new RuntimeException();
12640 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012641 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012642 }
12643
12644 mAdjSeq++;
12645
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012646 // Let's determine how many processes we have running vs.
12647 // how many slots we have for background processes; we may want
12648 // to put multiple processes in a slot of there are enough of
12649 // them.
12650 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12651 int factor = (mLruProcesses.size()-4)/numSlots;
12652 if (factor < 1) factor = 1;
12653 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012654 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012656 // First try updating the OOM adjustment for each of the
12657 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012658 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012659 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12660 while (i > 0) {
12661 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012662 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012663 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012664 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012665 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012666 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012667 step++;
12668 if (step >= factor) {
12669 step = 0;
12670 curHiddenAdj++;
12671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012672 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012673 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012674 if (!app.killedBackground) {
12675 numHidden++;
12676 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012677 Slog.i(TAG, "No longer want " + app.processName
12678 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012679 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12680 app.processName, app.setAdj, "too many background");
12681 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012682 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012683 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012684 }
12685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012686 } else {
12687 didOomAdj = false;
12688 }
12689 }
12690
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012691 // If we return false, we will fall back on killing processes to
12692 // have a fixed limit. Do this if a limit has been requested; else
12693 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012694 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12695 }
12696
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012697 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012698 synchronized (this) {
12699 int i;
12700
12701 // First remove any unused application processes whose package
12702 // has been removed.
12703 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12704 final ProcessRecord app = mRemovedProcesses.get(i);
12705 if (app.activities.size() == 0
12706 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012707 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012708 TAG, "Exiting empty application process "
12709 + app.processName + " ("
12710 + (app.thread != null ? app.thread.asBinder() : null)
12711 + ")\n");
12712 if (app.pid > 0 && app.pid != MY_PID) {
12713 Process.killProcess(app.pid);
12714 } else {
12715 try {
12716 app.thread.scheduleExit();
12717 } catch (Exception e) {
12718 // Ignore exceptions.
12719 }
12720 }
12721 cleanUpApplicationRecordLocked(app, false, -1);
12722 mRemovedProcesses.remove(i);
12723
12724 if (app.persistent) {
12725 if (app.persistent) {
12726 addAppLocked(app.info);
12727 }
12728 }
12729 }
12730 }
12731
12732 // Now try updating the OOM adjustment for each of the
12733 // application processes based on their current state.
12734 // If the setOomAdj() API is not supported, then go with our
12735 // back-up plan...
12736 if (!updateOomAdjLocked()) {
12737
12738 // Count how many processes are running services.
12739 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012740 for (i=mLruProcesses.size()-1; i>=0; i--) {
12741 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012742
12743 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012744 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012745 // Don't count processes holding services against our
12746 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012747 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012748 TAG, "Not trimming app " + app + " with services: "
12749 + app.services);
12750 numServiceProcs++;
12751 }
12752 }
12753
12754 int curMaxProcs = mProcessLimit;
12755 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12756 if (mAlwaysFinishActivities) {
12757 curMaxProcs = 1;
12758 }
12759 curMaxProcs += numServiceProcs;
12760
12761 // Quit as many processes as we can to get down to the desired
12762 // process count. First remove any processes that no longer
12763 // have activites running in them.
12764 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012765 i<mLruProcesses.size()
12766 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012767 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012768 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012769 // Quit an application only if it is not currently
12770 // running any activities.
12771 if (!app.persistent && app.activities.size() == 0
12772 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012773 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012774 TAG, "Exiting empty application process "
12775 + app.processName + " ("
12776 + (app.thread != null ? app.thread.asBinder() : null)
12777 + ")\n");
12778 if (app.pid > 0 && app.pid != MY_PID) {
12779 Process.killProcess(app.pid);
12780 } else {
12781 try {
12782 app.thread.scheduleExit();
12783 } catch (Exception e) {
12784 // Ignore exceptions.
12785 }
12786 }
12787 // todo: For now we assume the application is not buggy
12788 // or evil, and will quit as a result of our request.
12789 // Eventually we need to drive this off of the death
12790 // notification, and kill the process if it takes too long.
12791 cleanUpApplicationRecordLocked(app, false, i);
12792 i--;
12793 }
12794 }
12795
12796 // If we still have too many processes, now from the least
12797 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012798 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012799 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012800 " of " + curMaxProcs + " processes");
12801 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012802 i<mLruProcesses.size()
12803 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012804 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012805 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012806 // Quit the application only if we have a state saved for
12807 // all of its activities.
12808 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012809 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012810 int NUMA = app.activities.size();
12811 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012812 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012813 TAG, "Looking to quit " + app.processName);
12814 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012815 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012816 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012817 TAG, " " + r.intent.getComponent().flattenToShortString()
12818 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12819 canQuit = (r.haveState || !r.stateNotNeeded)
12820 && !r.visible && r.stopped;
12821 }
12822 if (canQuit) {
12823 // Finish all of the activities, and then the app itself.
12824 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012825 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012826 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012827 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012828 }
12829 r.resultTo = null;
12830 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012831 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012832 + app.processName + " ("
12833 + (app.thread != null ? app.thread.asBinder() : null)
12834 + ")\n");
12835 if (app.pid > 0 && app.pid != MY_PID) {
12836 Process.killProcess(app.pid);
12837 } else {
12838 try {
12839 app.thread.scheduleExit();
12840 } catch (Exception e) {
12841 // Ignore exceptions.
12842 }
12843 }
12844 // todo: For now we assume the application is not buggy
12845 // or evil, and will quit as a result of our request.
12846 // Eventually we need to drive this off of the death
12847 // notification, and kill the process if it takes too long.
12848 cleanUpApplicationRecordLocked(app, false, i);
12849 i--;
12850 //dump();
12851 }
12852 }
12853
12854 }
12855
12856 int curMaxActivities = MAX_ACTIVITIES;
12857 if (mAlwaysFinishActivities) {
12858 curMaxActivities = 1;
12859 }
12860
12861 // Finally, if there are too many activities now running, try to
12862 // finish as many as we can to get back down to the limit.
12863 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012864 i<mMainStack.mLRUActivities.size()
12865 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012866 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012867 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012868 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012869
12870 // We can finish this one if we have its icicle saved and
12871 // it is not persistent.
12872 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012873 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012874 final int origSize = mMainStack.mLRUActivities.size();
12875 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012876
12877 // This will remove it from the LRU list, so keep
12878 // our index at the same value. Note that this check to
12879 // see if the size changes is just paranoia -- if
12880 // something unexpected happens, we don't want to end up
12881 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012882 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012883 i--;
12884 }
12885 }
12886 }
12887 }
12888 }
12889
12890 /** This method sends the specified signal to each of the persistent apps */
12891 public void signalPersistentProcesses(int sig) throws RemoteException {
12892 if (sig != Process.SIGNAL_USR1) {
12893 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12894 }
12895
12896 synchronized (this) {
12897 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12898 != PackageManager.PERMISSION_GRANTED) {
12899 throw new SecurityException("Requires permission "
12900 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12901 }
12902
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012903 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12904 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012905 if (r.thread != null && r.persistent) {
12906 Process.sendSignal(r.pid, sig);
12907 }
12908 }
12909 }
12910 }
12911
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012912 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012913 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012914
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012915 try {
12916 synchronized (this) {
12917 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12918 // its own permission.
12919 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12920 != PackageManager.PERMISSION_GRANTED) {
12921 throw new SecurityException("Requires permission "
12922 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012923 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012924
12925 if (start && fd == null) {
12926 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012927 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012928
12929 ProcessRecord proc = null;
12930 try {
12931 int pid = Integer.parseInt(process);
12932 synchronized (mPidsSelfLocked) {
12933 proc = mPidsSelfLocked.get(pid);
12934 }
12935 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012936 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012937
12938 if (proc == null) {
12939 HashMap<String, SparseArray<ProcessRecord>> all
12940 = mProcessNames.getMap();
12941 SparseArray<ProcessRecord> procs = all.get(process);
12942 if (procs != null && procs.size() > 0) {
12943 proc = procs.valueAt(0);
12944 }
12945 }
12946
12947 if (proc == null || proc.thread == null) {
12948 throw new IllegalArgumentException("Unknown process: " + process);
12949 }
12950
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080012951 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
12952 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012953 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12954 throw new SecurityException("Process not debuggable: " + proc);
12955 }
12956 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012957
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012958 proc.thread.profilerControl(start, path, fd);
12959 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012960 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012961 }
12962 } catch (RemoteException e) {
12963 throw new IllegalStateException("Process disappeared");
12964 } finally {
12965 if (fd != null) {
12966 try {
12967 fd.close();
12968 } catch (IOException e) {
12969 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012970 }
12971 }
12972 }
Andy McFadden824c5102010-07-09 16:26:57 -070012973
12974 public boolean dumpHeap(String process, boolean managed,
12975 String path, ParcelFileDescriptor fd) throws RemoteException {
12976
12977 try {
12978 synchronized (this) {
12979 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12980 // its own permission (same as profileControl).
12981 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12982 != PackageManager.PERMISSION_GRANTED) {
12983 throw new SecurityException("Requires permission "
12984 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12985 }
12986
12987 if (fd == null) {
12988 throw new IllegalArgumentException("null fd");
12989 }
12990
12991 ProcessRecord proc = null;
12992 try {
12993 int pid = Integer.parseInt(process);
12994 synchronized (mPidsSelfLocked) {
12995 proc = mPidsSelfLocked.get(pid);
12996 }
12997 } catch (NumberFormatException e) {
12998 }
12999
13000 if (proc == null) {
13001 HashMap<String, SparseArray<ProcessRecord>> all
13002 = mProcessNames.getMap();
13003 SparseArray<ProcessRecord> procs = all.get(process);
13004 if (procs != null && procs.size() > 0) {
13005 proc = procs.valueAt(0);
13006 }
13007 }
13008
13009 if (proc == null || proc.thread == null) {
13010 throw new IllegalArgumentException("Unknown process: " + process);
13011 }
13012
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013013 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13014 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013015 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13016 throw new SecurityException("Process not debuggable: " + proc);
13017 }
13018 }
13019
13020 proc.thread.dumpHeap(managed, path, fd);
13021 fd = null;
13022 return true;
13023 }
13024 } catch (RemoteException e) {
13025 throw new IllegalStateException("Process disappeared");
13026 } finally {
13027 if (fd != null) {
13028 try {
13029 fd.close();
13030 } catch (IOException e) {
13031 }
13032 }
13033 }
13034 }
13035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013036 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13037 public void monitor() {
13038 synchronized (this) { }
13039 }
13040}