blob: 40417b18daa911eed300127efa1b140b7ab727bd [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
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800720 CoreSettingsObserver mCoreSettingsObserver;
721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 /**
723 * Thread-local storage used to carry caller permissions over through
724 * indirect content-provider access.
725 * @see #ActivityManagerService.openContentUri()
726 */
727 private class Identity {
728 public int pid;
729 public int uid;
730
731 Identity(int _pid, int _uid) {
732 pid = _pid;
733 uid = _uid;
734 }
735 }
736 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
737
738 /**
739 * All information we have collected about the runtime performance of
740 * any user id that can impact battery performance.
741 */
742 final BatteryStatsService mBatteryStatsService;
743
744 /**
745 * information about component usage
746 */
747 final UsageStatsService mUsageStatsService;
748
749 /**
750 * Current configuration information. HistoryRecord objects are given
751 * a reference to this object to indicate which configuration they are
752 * currently running in, so this object must be kept immutable.
753 */
754 Configuration mConfiguration = new Configuration();
755
756 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800757 * Current sequencing integer of the configuration, for skipping old
758 * configurations.
759 */
760 int mConfigurationSeq = 0;
761
762 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700763 * Hardware-reported OpenGLES version.
764 */
765 final int GL_ES_VERSION;
766
767 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 * List of initialization arguments to pass to all processes when binding applications to them.
769 * For example, references to the commonly used services.
770 */
771 HashMap<String, IBinder> mAppBindArgs;
772
773 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700774 * Temporary to avoid allocations. Protected by main lock.
775 */
776 final StringBuilder mStringBuilder = new StringBuilder(256);
777
778 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 * Used to control how we initialize the service.
780 */
781 boolean mStartRunning = false;
782 ComponentName mTopComponent;
783 String mTopAction;
784 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700785 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 boolean mSystemReady = false;
787 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700788 boolean mWaitingUpdate = false;
789 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700790 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700791 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792
793 Context mContext;
794
795 int mFactoryTest;
796
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700797 boolean mCheckedForSetup;
798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700800 * The time at which we will allow normal application switches again,
801 * after a call to {@link #stopAppSwitches()}.
802 */
803 long mAppSwitchesAllowedTime;
804
805 /**
806 * This is set to true after the first switch after mAppSwitchesAllowedTime
807 * is set; any switches after that will clear the time.
808 */
809 boolean mDidAppSwitch;
810
811 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700812 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700813 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700814 long mLastPowerCheckRealtime;
815
816 /**
817 * Last time (in uptime) at which we checked for power usage.
818 */
819 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700820
821 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 * Set while we are wanting to sleep, to prevent any
823 * activities from being started/resumed.
824 */
825 boolean mSleeping = false;
826
827 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700828 * Set if we are shutting down the system, similar to sleeping.
829 */
830 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831
832 /**
833 * Task identifier that activities are currently being started
834 * in. Incremented each time a new task is created.
835 * todo: Replace this with a TokenSpace class that generates non-repeating
836 * integers that won't wrap.
837 */
838 int mCurTask = 1;
839
840 /**
841 * Current sequence id for oom_adj computation traversal.
842 */
843 int mAdjSeq = 0;
844
845 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700846 * Current sequence id for process LRU updating.
847 */
848 int mLruSeq = 0;
849
850 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
852 * is set, indicating the user wants processes started in such a way
853 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
854 * running in each process (thus no pre-initialized process, etc).
855 */
856 boolean mSimpleProcessManagement = false;
857
858 /**
859 * System monitoring: number of processes that died since the last
860 * N procs were started.
861 */
862 int[] mProcDeaths = new int[20];
863
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700864 /**
865 * This is set if we had to do a delayed dexopt of an app before launching
866 * it, to increasing the ANR timeouts in that case.
867 */
868 boolean mDidDexOpt;
869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 String mDebugApp = null;
871 boolean mWaitForDebugger = false;
872 boolean mDebugTransient = false;
873 String mOrigDebugApp = null;
874 boolean mOrigWaitForDebugger = false;
875 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700876 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700878 final RemoteCallbackList<IActivityWatcher> mWatchers
879 = new RemoteCallbackList<IActivityWatcher>();
880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 /**
882 * Callback of last caller to {@link #requestPss}.
883 */
884 Runnable mRequestPssCallback;
885
886 /**
887 * Remaining processes for which we are waiting results from the last
888 * call to {@link #requestPss}.
889 */
890 final ArrayList<ProcessRecord> mRequestPssList
891 = new ArrayList<ProcessRecord>();
892
893 /**
894 * Runtime statistics collection thread. This object's lock is used to
895 * protect all related state.
896 */
897 final Thread mProcessStatsThread;
898
899 /**
900 * Used to collect process stats when showing not responding dialog.
901 * Protected by mProcessStatsThread.
902 */
903 final ProcessStats mProcessStats = new ProcessStats(
904 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700905 final AtomicLong mLastCpuTime = new AtomicLong(0);
906 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 long mLastWriteTime = 0;
909
910 /**
911 * Set to true after the system has finished booting.
912 */
913 boolean mBooted = false;
914
915 int mProcessLimit = 0;
916
917 WindowManagerService mWindowManager;
918
919 static ActivityManagerService mSelf;
920 static ActivityThread mSystemThread;
921
922 private final class AppDeathRecipient implements IBinder.DeathRecipient {
923 final ProcessRecord mApp;
924 final int mPid;
925 final IApplicationThread mAppThread;
926
927 AppDeathRecipient(ProcessRecord app, int pid,
928 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800929 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 TAG, "New death recipient " + this
931 + " for thread " + thread.asBinder());
932 mApp = app;
933 mPid = pid;
934 mAppThread = thread;
935 }
936
937 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800938 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 TAG, "Death received in " + this
940 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 synchronized(ActivityManagerService.this) {
942 appDiedLocked(mApp, mPid, mAppThread);
943 }
944 }
945 }
946
947 static final int SHOW_ERROR_MSG = 1;
948 static final int SHOW_NOT_RESPONDING_MSG = 2;
949 static final int SHOW_FACTORY_ERROR_MSG = 3;
950 static final int UPDATE_CONFIGURATION_MSG = 4;
951 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
952 static final int WAIT_FOR_DEBUGGER_MSG = 6;
953 static final int BROADCAST_INTENT_MSG = 7;
954 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 static final int SERVICE_TIMEOUT_MSG = 12;
956 static final int UPDATE_TIME_ZONE = 13;
957 static final int SHOW_UID_ERROR_MSG = 14;
958 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700960 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700961 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800962 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700963 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
964 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700965 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700966 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700967 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700968 static final int UPDATE_HTTP_PROXY = 29;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969
970 AlertDialog mUidAlert;
971
972 final Handler mHandler = new Handler() {
973 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800974 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 //}
976
977 public void handleMessage(Message msg) {
978 switch (msg.what) {
979 case SHOW_ERROR_MSG: {
980 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 synchronized (ActivityManagerService.this) {
982 ProcessRecord proc = (ProcessRecord)data.get("app");
983 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800984 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800985 return;
986 }
987 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700988 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800989 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 d.show();
991 proc.crashDialog = d;
992 } else {
993 // The device is asleep, so just pretend that the user
994 // saw a crash dialog and hit "force quit".
995 res.set(0);
996 }
997 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700998
999 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 } break;
1001 case SHOW_NOT_RESPONDING_MSG: {
1002 synchronized (ActivityManagerService.this) {
1003 HashMap data = (HashMap) msg.obj;
1004 ProcessRecord proc = (ProcessRecord)data.get("app");
1005 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001006 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 return;
1008 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001009
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001010 Intent intent = new Intent("android.intent.action.ANR");
1011 if (!mProcessesReady) {
1012 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1013 }
1014 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001015 null, null, 0, null, null, null,
1016 false, false, MY_PID, Process.SYSTEM_UID);
1017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001019 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 d.show();
1021 proc.anrDialog = d;
1022 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001023
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001024 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001026 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1027 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1028 synchronized (ActivityManagerService.this) {
1029 ProcessRecord proc = (ProcessRecord) data.get("app");
1030 if (proc == null) {
1031 Slog.e(TAG, "App not found when showing strict mode dialog.");
1032 break;
1033 }
1034 if (proc.crashDialog != null) {
1035 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1036 return;
1037 }
1038 AppErrorResult res = (AppErrorResult) data.get("result");
1039 if (!mSleeping && !mShuttingDown) {
1040 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1041 d.show();
1042 proc.crashDialog = d;
1043 } else {
1044 // The device is asleep, so just pretend that the user
1045 // saw a crash dialog and hit "force quit".
1046 res.set(0);
1047 }
1048 }
1049 ensureBootCompleted();
1050 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 case SHOW_FACTORY_ERROR_MSG: {
1052 Dialog d = new FactoryErrorDialog(
1053 mContext, msg.getData().getCharSequence("msg"));
1054 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001055 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 } break;
1057 case UPDATE_CONFIGURATION_MSG: {
1058 final ContentResolver resolver = mContext.getContentResolver();
1059 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1060 } break;
1061 case GC_BACKGROUND_PROCESSES_MSG: {
1062 synchronized (ActivityManagerService.this) {
1063 performAppGcsIfAppropriateLocked();
1064 }
1065 } break;
1066 case WAIT_FOR_DEBUGGER_MSG: {
1067 synchronized (ActivityManagerService.this) {
1068 ProcessRecord app = (ProcessRecord)msg.obj;
1069 if (msg.arg1 != 0) {
1070 if (!app.waitedForDebugger) {
1071 Dialog d = new AppWaitingForDebuggerDialog(
1072 ActivityManagerService.this,
1073 mContext, app);
1074 app.waitDialog = d;
1075 app.waitedForDebugger = true;
1076 d.show();
1077 }
1078 } else {
1079 if (app.waitDialog != null) {
1080 app.waitDialog.dismiss();
1081 app.waitDialog = null;
1082 }
1083 }
1084 }
1085 } break;
1086 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001087 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 TAG, "Received BROADCAST_INTENT_MSG");
1089 processNextBroadcast(true);
1090 } break;
1091 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001092 synchronized (ActivityManagerService.this) {
1093 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001095 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001097 if (mDidDexOpt) {
1098 mDidDexOpt = false;
1099 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1100 nmsg.obj = msg.obj;
1101 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1102 return;
1103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 serviceTimeout((ProcessRecord)msg.obj);
1105 } break;
1106 case UPDATE_TIME_ZONE: {
1107 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001108 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1109 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 if (r.thread != null) {
1111 try {
1112 r.thread.updateTimeZone();
1113 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001114 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 }
1116 }
1117 }
1118 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001119 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001120 case CLEAR_DNS_CACHE: {
1121 synchronized (ActivityManagerService.this) {
1122 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1123 ProcessRecord r = mLruProcesses.get(i);
1124 if (r.thread != null) {
1125 try {
1126 r.thread.clearDnsCache();
1127 } catch (RemoteException ex) {
1128 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1129 }
1130 }
1131 }
1132 }
1133 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001134 case UPDATE_HTTP_PROXY: {
1135 ProxyProperties proxy = (ProxyProperties)msg.obj;
1136 String host = "";
1137 String port = "";
1138 String exclList = "";
1139 if (proxy != null) {
1140 host = proxy.getHost();
1141 port = Integer.toString(proxy.getPort());
1142 exclList = proxy.getExclusionList();
1143 }
1144 synchronized (ActivityManagerService.this) {
1145 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1146 ProcessRecord r = mLruProcesses.get(i);
1147 if (r.thread != null) {
1148 try {
1149 r.thread.setHttpProxy(host, port, exclList);
1150 } catch (RemoteException ex) {
1151 Slog.w(TAG, "Failed to update http proxy for: " +
1152 r.info.processName);
1153 }
1154 }
1155 }
1156 }
1157 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 case SHOW_UID_ERROR_MSG: {
1159 // XXX This is a temporary dialog, no need to localize.
1160 AlertDialog d = new BaseErrorDialog(mContext);
1161 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1162 d.setCancelable(false);
1163 d.setTitle("System UIDs Inconsistent");
1164 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 +02001165 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1167 mUidAlert = d;
1168 d.show();
1169 } break;
1170 case IM_FEELING_LUCKY_MSG: {
1171 if (mUidAlert != null) {
1172 mUidAlert.dismiss();
1173 mUidAlert = null;
1174 }
1175 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001177 if (mDidDexOpt) {
1178 mDidDexOpt = false;
1179 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1180 nmsg.obj = msg.obj;
1181 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1182 return;
1183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 ProcessRecord app = (ProcessRecord)msg.obj;
1185 synchronized (ActivityManagerService.this) {
1186 processStartTimedOutLocked(app);
1187 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001188 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001189 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1190 synchronized (ActivityManagerService.this) {
1191 doPendingActivityLaunchesLocked(true);
1192 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001193 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001194 case KILL_APPLICATION_MSG: {
1195 synchronized (ActivityManagerService.this) {
1196 int uid = msg.arg1;
1197 boolean restart = (msg.arg2 == 1);
1198 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001199 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001200 }
1201 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001202 case FINALIZE_PENDING_INTENT_MSG: {
1203 ((PendingIntentRecord)msg.obj).completeFinalize();
1204 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001205 case POST_HEAVY_NOTIFICATION_MSG: {
1206 INotificationManager inm = NotificationManager.getService();
1207 if (inm == null) {
1208 return;
1209 }
1210
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001211 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001212 ProcessRecord process = root.app;
1213 if (process == null) {
1214 return;
1215 }
1216
1217 try {
1218 Context context = mContext.createPackageContext(process.info.packageName, 0);
1219 String text = mContext.getString(R.string.heavy_weight_notification,
1220 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1221 Notification notification = new Notification();
1222 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1223 notification.when = 0;
1224 notification.flags = Notification.FLAG_ONGOING_EVENT;
1225 notification.tickerText = text;
1226 notification.defaults = 0; // please be quiet
1227 notification.sound = null;
1228 notification.vibrate = null;
1229 notification.setLatestEventInfo(context, text,
1230 mContext.getText(R.string.heavy_weight_notification_detail),
1231 PendingIntent.getActivity(mContext, 0, root.intent,
1232 PendingIntent.FLAG_CANCEL_CURRENT));
1233
1234 try {
1235 int[] outId = new int[1];
1236 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1237 notification, outId);
1238 } catch (RuntimeException e) {
1239 Slog.w(ActivityManagerService.TAG,
1240 "Error showing notification for heavy-weight app", e);
1241 } catch (RemoteException e) {
1242 }
1243 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001244 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001245 }
1246 } break;
1247 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1248 INotificationManager inm = NotificationManager.getService();
1249 if (inm == null) {
1250 return;
1251 }
1252 try {
1253 inm.cancelNotification("android",
1254 R.string.heavy_weight_notification);
1255 } catch (RuntimeException e) {
1256 Slog.w(ActivityManagerService.TAG,
1257 "Error canceling notification for service", e);
1258 } catch (RemoteException e) {
1259 }
1260 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001261 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1262 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001263 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001264 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001265 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1266 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001267 }
1268 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001269 }
1270 }
1271 };
1272
1273 public static void setSystemProcess() {
1274 try {
1275 ActivityManagerService m = mSelf;
1276
1277 ServiceManager.addService("activity", m);
1278 ServiceManager.addService("meminfo", new MemBinder(m));
1279 if (MONITOR_CPU_USAGE) {
1280 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282 ServiceManager.addService("permission", new PermissionController(m));
1283
1284 ApplicationInfo info =
1285 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001286 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001287 mSystemThread.installSystemApplicationInfo(info);
1288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 synchronized (mSelf) {
1290 ProcessRecord app = mSelf.newProcessRecordLocked(
1291 mSystemThread.getApplicationThread(), info,
1292 info.processName);
1293 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001294 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001295 app.maxAdj = SYSTEM_ADJ;
1296 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1297 synchronized (mSelf.mPidsSelfLocked) {
1298 mSelf.mPidsSelfLocked.put(app.pid, app);
1299 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001300 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301 }
1302 } catch (PackageManager.NameNotFoundException e) {
1303 throw new RuntimeException(
1304 "Unable to find android system package", e);
1305 }
1306 }
1307
1308 public void setWindowManager(WindowManagerService wm) {
1309 mWindowManager = wm;
1310 }
1311
1312 public static final Context main(int factoryTest) {
1313 AThread thr = new AThread();
1314 thr.start();
1315
1316 synchronized (thr) {
1317 while (thr.mService == null) {
1318 try {
1319 thr.wait();
1320 } catch (InterruptedException e) {
1321 }
1322 }
1323 }
1324
1325 ActivityManagerService m = thr.mService;
1326 mSelf = m;
1327 ActivityThread at = ActivityThread.systemMain();
1328 mSystemThread = at;
1329 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001330 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 m.mContext = context;
1332 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001333 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334
1335 m.mBatteryStatsService.publish(context);
1336 m.mUsageStatsService.publish(context);
1337
1338 synchronized (thr) {
1339 thr.mReady = true;
1340 thr.notifyAll();
1341 }
1342
1343 m.startRunning(null, null, null, null);
1344
1345 return context;
1346 }
1347
1348 public static ActivityManagerService self() {
1349 return mSelf;
1350 }
1351
1352 static class AThread extends Thread {
1353 ActivityManagerService mService;
1354 boolean mReady = false;
1355
1356 public AThread() {
1357 super("ActivityManager");
1358 }
1359
1360 public void run() {
1361 Looper.prepare();
1362
1363 android.os.Process.setThreadPriority(
1364 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001365 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366
1367 ActivityManagerService m = new ActivityManagerService();
1368
1369 synchronized (this) {
1370 mService = m;
1371 notifyAll();
1372 }
1373
1374 synchronized (this) {
1375 while (!mReady) {
1376 try {
1377 wait();
1378 } catch (InterruptedException e) {
1379 }
1380 }
1381 }
1382
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001383 // For debug builds, log event loop stalls to dropbox for analysis.
1384 if (StrictMode.conditionallyEnableDebugLogging()) {
1385 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1386 }
1387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388 Looper.loop();
1389 }
1390 }
1391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 static class MemBinder extends Binder {
1393 ActivityManagerService mActivityManagerService;
1394 MemBinder(ActivityManagerService activityManagerService) {
1395 mActivityManagerService = activityManagerService;
1396 }
1397
1398 @Override
1399 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1400 ActivityManagerService service = mActivityManagerService;
1401 ArrayList<ProcessRecord> procs;
1402 synchronized (mActivityManagerService) {
1403 if (args != null && args.length > 0
1404 && args[0].charAt(0) != '-') {
1405 procs = new ArrayList<ProcessRecord>();
1406 int pid = -1;
1407 try {
1408 pid = Integer.parseInt(args[0]);
1409 } catch (NumberFormatException e) {
1410
1411 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001412 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1413 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 if (proc.pid == pid) {
1415 procs.add(proc);
1416 } else if (proc.processName.equals(args[0])) {
1417 procs.add(proc);
1418 }
1419 }
1420 if (procs.size() <= 0) {
1421 pw.println("No process found for: " + args[0]);
1422 return;
1423 }
1424 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001425 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 }
1427 }
1428 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1429 }
1430 }
1431
1432 static class CpuBinder extends Binder {
1433 ActivityManagerService mActivityManagerService;
1434 CpuBinder(ActivityManagerService activityManagerService) {
1435 mActivityManagerService = activityManagerService;
1436 }
1437
1438 @Override
1439 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1440 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001441 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1442 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1443 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 }
1445 }
1446 }
1447
1448 private ActivityManagerService() {
1449 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1450 if (v != null && Integer.getInteger(v) != 0) {
1451 mSimpleProcessManagement = true;
1452 }
1453 v = System.getenv("ANDROID_DEBUG_APP");
1454 if (v != null) {
1455 mSimpleProcessManagement = true;
1456 }
1457
Joe Onorato8a9b2202010-02-26 18:56:32 -08001458 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 File dataDir = Environment.getDataDirectory();
1461 File systemDir = new File(dataDir, "system");
1462 systemDir.mkdirs();
1463 mBatteryStatsService = new BatteryStatsService(new File(
1464 systemDir, "batterystats.bin").toString());
1465 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001466 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001467 mOnBattery = DEBUG_POWER ? true
1468 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001469 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001471 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001472 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473
Jack Palevichb90d28c2009-07-22 15:35:24 -07001474 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1475 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1476
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001477 mConfiguration.setToDefaults();
1478 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 mProcessStats.init();
1480
1481 // Add ourself to the Watchdog monitors.
1482 Watchdog.getInstance().addMonitor(this);
1483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 mProcessStatsThread = new Thread("ProcessStats") {
1485 public void run() {
1486 while (true) {
1487 try {
1488 try {
1489 synchronized(this) {
1490 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001491 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001493 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 // + ", write delay=" + nextWriteDelay);
1495 if (nextWriteDelay < nextCpuDelay) {
1496 nextCpuDelay = nextWriteDelay;
1497 }
1498 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001499 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 this.wait(nextCpuDelay);
1501 }
1502 }
1503 } catch (InterruptedException e) {
1504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 updateCpuStatsNow();
1506 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001507 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 }
1509 }
1510 }
1511 };
1512 mProcessStatsThread.start();
1513 }
1514
1515 @Override
1516 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1517 throws RemoteException {
1518 try {
1519 return super.onTransact(code, data, reply, flags);
1520 } catch (RuntimeException e) {
1521 // The activity manager only throws security exceptions, so let's
1522 // log all others.
1523 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001524 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001525 }
1526 throw e;
1527 }
1528 }
1529
1530 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001531 final long now = SystemClock.uptimeMillis();
1532 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1533 return;
1534 }
1535 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1536 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 mProcessStatsThread.notify();
1538 }
1539 }
1540 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 void updateCpuStatsNow() {
1543 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001544 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 final long now = SystemClock.uptimeMillis();
1546 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001549 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1550 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 haveNewCpuStats = true;
1552 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001553 //Slog.i(TAG, mProcessStats.printCurrentState());
1554 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 // + mProcessStats.getTotalCpuPercent() + "%");
1556
Joe Onorato8a9b2202010-02-26 18:56:32 -08001557 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 if ("true".equals(SystemProperties.get("events.cpu"))) {
1559 int user = mProcessStats.getLastUserTime();
1560 int system = mProcessStats.getLastSystemTime();
1561 int iowait = mProcessStats.getLastIoWaitTime();
1562 int irq = mProcessStats.getLastIrqTime();
1563 int softIrq = mProcessStats.getLastSoftIrqTime();
1564 int idle = mProcessStats.getLastIdleTime();
1565
1566 int total = user + system + iowait + irq + softIrq + idle;
1567 if (total == 0) total = 1;
1568
Doug Zongker2bec3d42009-12-04 12:52:44 -08001569 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 ((user+system+iowait+irq+softIrq) * 100) / total,
1571 (user * 100) / total,
1572 (system * 100) / total,
1573 (iowait * 100) / total,
1574 (irq * 100) / total,
1575 (softIrq * 100) / total);
1576 }
1577 }
1578
Amith Yamasanie43530a2009-08-21 13:11:37 -07001579 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001580 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001581 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 synchronized(mPidsSelfLocked) {
1583 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001584 if (mOnBattery) {
1585 int perc = bstats.startAddingCpuLocked();
1586 int totalUTime = 0;
1587 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001588 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001590 ProcessStats.Stats st = mProcessStats.getStats(i);
1591 if (!st.working) {
1592 continue;
1593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001595 int otherUTime = (st.rel_utime*perc)/100;
1596 int otherSTime = (st.rel_stime*perc)/100;
1597 totalUTime += otherUTime;
1598 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 if (pr != null) {
1600 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001601 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1602 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001603 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001604 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001605 } else {
1606 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001607 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001608 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001609 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1610 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001611 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 }
1614 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001615 bstats.finishAddingCpuLocked(perc, totalUTime,
1616 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 }
1618 }
1619 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1622 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001623 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 }
1625 }
1626 }
1627 }
1628
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001629 @Override
1630 public void batteryNeedsCpuUpdate() {
1631 updateCpuStatsNow();
1632 }
1633
1634 @Override
1635 public void batteryPowerChanged(boolean onBattery) {
1636 // When plugging in, update the CPU stats first before changing
1637 // the plug state.
1638 updateCpuStatsNow();
1639 synchronized (this) {
1640 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001641 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001642 }
1643 }
1644 }
1645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 /**
1647 * Initialize the application bind args. These are passed to each
1648 * process when the bindApplication() IPC is sent to the process. They're
1649 * lazily setup to make sure the services are running when they're asked for.
1650 */
1651 private HashMap<String, IBinder> getCommonServicesLocked() {
1652 if (mAppBindArgs == null) {
1653 mAppBindArgs = new HashMap<String, IBinder>();
1654
1655 // Setup the application init args
1656 mAppBindArgs.put("package", ServiceManager.getService("package"));
1657 mAppBindArgs.put("window", ServiceManager.getService("window"));
1658 mAppBindArgs.put(Context.ALARM_SERVICE,
1659 ServiceManager.getService(Context.ALARM_SERVICE));
1660 }
1661 return mAppBindArgs;
1662 }
1663
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001664 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 if (mFocusedActivity != r) {
1666 mFocusedActivity = r;
1667 mWindowManager.setFocusedApp(r, true);
1668 }
1669 }
1670
Dianne Hackborn906497c2010-05-10 15:57:38 -07001671 private final void updateLruProcessInternalLocked(ProcessRecord app,
1672 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001674 int lrui = mLruProcesses.indexOf(app);
1675 if (lrui >= 0) mLruProcesses.remove(lrui);
1676
1677 int i = mLruProcesses.size()-1;
1678 int skipTop = 0;
1679
Dianne Hackborn906497c2010-05-10 15:57:38 -07001680 app.lruSeq = mLruSeq;
1681
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001682 // compute the new weight for this process.
1683 if (updateActivityTime) {
1684 app.lastActivityTime = SystemClock.uptimeMillis();
1685 }
1686 if (app.activities.size() > 0) {
1687 // If this process has activities, we more strongly want to keep
1688 // it around.
1689 app.lruWeight = app.lastActivityTime;
1690 } else if (app.pubProviders.size() > 0) {
1691 // If this process contains content providers, we want to keep
1692 // it a little more strongly.
1693 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1694 // Also don't let it kick out the first few "real" hidden processes.
1695 skipTop = MIN_HIDDEN_APPS;
1696 } else {
1697 // If this process doesn't have activities, we less strongly
1698 // want to keep it around, and generally want to avoid getting
1699 // in front of any very recently used activities.
1700 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1701 // Also don't let it kick out the first few "real" hidden processes.
1702 skipTop = MIN_HIDDEN_APPS;
1703 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001704
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001705 while (i >= 0) {
1706 ProcessRecord p = mLruProcesses.get(i);
1707 // If this app shouldn't be in front of the first N background
1708 // apps, then skip over that many that are currently hidden.
1709 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1710 skipTop--;
1711 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001712 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001713 mLruProcesses.add(i+1, app);
1714 break;
1715 }
1716 i--;
1717 }
1718 if (i < 0) {
1719 mLruProcesses.add(0, app);
1720 }
1721
Dianne Hackborn906497c2010-05-10 15:57:38 -07001722 // If the app is currently using a content provider or service,
1723 // bump those processes as well.
1724 if (app.connections.size() > 0) {
1725 for (ConnectionRecord cr : app.connections) {
1726 if (cr.binding != null && cr.binding.service != null
1727 && cr.binding.service.app != null
1728 && cr.binding.service.app.lruSeq != mLruSeq) {
1729 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1730 updateActivityTime, i+1);
1731 }
1732 }
1733 }
1734 if (app.conProviders.size() > 0) {
1735 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1736 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1737 updateLruProcessInternalLocked(cpr.app, oomAdj,
1738 updateActivityTime, i+1);
1739 }
1740 }
1741 }
1742
Joe Onorato8a9b2202010-02-26 18:56:32 -08001743 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 if (oomAdj) {
1745 updateOomAdjLocked();
1746 }
1747 }
1748
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001749 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001750 boolean oomAdj, boolean updateActivityTime) {
1751 mLruSeq++;
1752 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1753 }
1754
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001755 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 String processName, int uid) {
1757 if (uid == Process.SYSTEM_UID) {
1758 // The system gets to run in any process. If there are multiple
1759 // processes with the same uid, just pick the first (this
1760 // should never happen).
1761 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1762 processName);
1763 return procs != null ? procs.valueAt(0) : null;
1764 }
1765 ProcessRecord proc = mProcessNames.get(processName, uid);
1766 return proc;
1767 }
1768
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001769 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001770 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001771 try {
1772 if (pm.performDexOpt(packageName)) {
1773 mDidDexOpt = true;
1774 }
1775 } catch (RemoteException e) {
1776 }
1777 }
1778
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001779 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 int transit = mWindowManager.getPendingAppTransition();
1781 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1782 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1783 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1784 }
1785
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001786 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001788 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1790 // We don't have to do anything more if:
1791 // (1) There is an existing application record; and
1792 // (2) The caller doesn't think it is dead, OR there is no thread
1793 // object attached to it so we know it couldn't have crashed; and
1794 // (3) There is a pid assigned to it, so it is either starting or
1795 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001796 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 + " app=" + app + " knownToBeDead=" + knownToBeDead
1798 + " thread=" + (app != null ? app.thread : null)
1799 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001800 if (app != null && app.pid > 0) {
1801 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001802 // We already have the app running, or are waiting for it to
1803 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001804 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001805 return app;
1806 } else {
1807 // An application record is attached to a previous process,
1808 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001809 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001810 handleAppDiedLocked(app, true);
1811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 String hostingNameStr = hostingName != null
1815 ? hostingName.flattenToShortString() : null;
1816
1817 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1818 // If we are in the background, then check to see if this process
1819 // is bad. If so, we will just silently fail.
1820 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001821 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1822 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 return null;
1824 }
1825 } else {
1826 // When the user is explicitly starting a process, then clear its
1827 // crash count so that we won't make it bad until they see at
1828 // least one crash dialog again, and make the process good again
1829 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001830 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1831 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 mProcessCrashTimes.remove(info.processName, info.uid);
1833 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001834 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 info.processName);
1836 mBadProcesses.remove(info.processName, info.uid);
1837 if (app != null) {
1838 app.bad = false;
1839 }
1840 }
1841 }
1842
1843 if (app == null) {
1844 app = newProcessRecordLocked(null, info, processName);
1845 mProcessNames.put(processName, info.uid, app);
1846 } else {
1847 // If this is a new package in the process, add the package to the list
1848 app.addPackage(info.packageName);
1849 }
1850
1851 // If the system is not ready yet, then hold off on starting this
1852 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001853 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001854 && !isAllowedWhileBooting(info)
1855 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 if (!mProcessesOnHold.contains(app)) {
1857 mProcessesOnHold.add(app);
1858 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001859 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 return app;
1861 }
1862
1863 startProcessLocked(app, hostingType, hostingNameStr);
1864 return (app.pid != 0) ? app : null;
1865 }
1866
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001867 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1868 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1869 }
1870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 private final void startProcessLocked(ProcessRecord app,
1872 String hostingType, String hostingNameStr) {
1873 if (app.pid > 0 && app.pid != MY_PID) {
1874 synchronized (mPidsSelfLocked) {
1875 mPidsSelfLocked.remove(app.pid);
1876 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1877 }
1878 app.pid = 0;
1879 }
1880
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001881 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1882 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 mProcessesOnHold.remove(app);
1884
1885 updateCpuStats();
1886
1887 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1888 mProcDeaths[0] = 0;
1889
1890 try {
1891 int uid = app.info.uid;
1892 int[] gids = null;
1893 try {
1894 gids = mContext.getPackageManager().getPackageGids(
1895 app.info.packageName);
1896 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001897 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001898 }
1899 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1900 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1901 && mTopComponent != null
1902 && app.processName.equals(mTopComponent.getPackageName())) {
1903 uid = 0;
1904 }
1905 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1906 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1907 uid = 0;
1908 }
1909 }
1910 int debugFlags = 0;
1911 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1912 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1913 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001914 // Run the app in safe mode if its manifest requests so or the
1915 // system is booted in safe mode.
1916 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1917 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001918 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1921 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1922 }
1923 if ("1".equals(SystemProperties.get("debug.assert"))) {
1924 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1925 }
1926 int pid = Process.start("android.app.ActivityThread",
1927 mSimpleProcessManagement ? app.processName : null, uid, uid,
1928 gids, debugFlags, null);
1929 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1930 synchronized (bs) {
1931 if (bs.isOnBattery()) {
1932 app.batteryStats.incStartsLocked();
1933 }
1934 }
1935
Doug Zongker2bec3d42009-12-04 12:52:44 -08001936 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 app.processName, hostingType,
1938 hostingNameStr != null ? hostingNameStr : "");
1939
1940 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001941 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 }
1943
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001944 StringBuilder buf = mStringBuilder;
1945 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 buf.append("Start proc ");
1947 buf.append(app.processName);
1948 buf.append(" for ");
1949 buf.append(hostingType);
1950 if (hostingNameStr != null) {
1951 buf.append(" ");
1952 buf.append(hostingNameStr);
1953 }
1954 buf.append(": pid=");
1955 buf.append(pid);
1956 buf.append(" uid=");
1957 buf.append(uid);
1958 buf.append(" gids={");
1959 if (gids != null) {
1960 for (int gi=0; gi<gids.length; gi++) {
1961 if (gi != 0) buf.append(", ");
1962 buf.append(gids[gi]);
1963
1964 }
1965 }
1966 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001967 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001968 if (pid == 0 || pid == MY_PID) {
1969 // Processes are being emulated with threads.
1970 app.pid = MY_PID;
1971 app.removed = false;
1972 mStartingProcesses.add(app);
1973 } else if (pid > 0) {
1974 app.pid = pid;
1975 app.removed = false;
1976 synchronized (mPidsSelfLocked) {
1977 this.mPidsSelfLocked.put(pid, app);
1978 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1979 msg.obj = app;
1980 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1981 }
1982 } else {
1983 app.pid = 0;
1984 RuntimeException e = new RuntimeException(
1985 "Failure starting process " + app.processName
1986 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001987 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001988 }
1989 } catch (RuntimeException e) {
1990 // XXX do better error recovery.
1991 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001992 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 }
1994 }
1995
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001996 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 if (resumed) {
1998 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1999 } else {
2000 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2001 }
2002 }
2003
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002004 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002005 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2006 && mTopAction == null) {
2007 // We are running in factory test mode, but unable to find
2008 // the factory test app, so just sit around displaying the
2009 // error message and don't try to start anything.
2010 return false;
2011 }
2012 Intent intent = new Intent(
2013 mTopAction,
2014 mTopData != null ? Uri.parse(mTopData) : null);
2015 intent.setComponent(mTopComponent);
2016 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2017 intent.addCategory(Intent.CATEGORY_HOME);
2018 }
2019 ActivityInfo aInfo =
2020 intent.resolveActivityInfo(mContext.getPackageManager(),
2021 STOCK_PM_FLAGS);
2022 if (aInfo != null) {
2023 intent.setComponent(new ComponentName(
2024 aInfo.applicationInfo.packageName, aInfo.name));
2025 // Don't do this if the home app is currently being
2026 // instrumented.
2027 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2028 aInfo.applicationInfo.uid);
2029 if (app == null || app.instrumentationClass == null) {
2030 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002031 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002032 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002033 }
2034 }
2035
2036
2037 return true;
2038 }
2039
2040 /**
2041 * Starts the "new version setup screen" if appropriate.
2042 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002043 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002044 // Only do this once per boot.
2045 if (mCheckedForSetup) {
2046 return;
2047 }
2048
2049 // We will show this screen if the current one is a different
2050 // version than the last one shown, and we are not running in
2051 // low-level factory test mode.
2052 final ContentResolver resolver = mContext.getContentResolver();
2053 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2054 Settings.Secure.getInt(resolver,
2055 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2056 mCheckedForSetup = true;
2057
2058 // See if we should be showing the platform update setup UI.
2059 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2060 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2061 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2062
2063 // We don't allow third party apps to replace this.
2064 ResolveInfo ri = null;
2065 for (int i=0; ris != null && i<ris.size(); i++) {
2066 if ((ris.get(i).activityInfo.applicationInfo.flags
2067 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2068 ri = ris.get(i);
2069 break;
2070 }
2071 }
2072
2073 if (ri != null) {
2074 String vers = ri.activityInfo.metaData != null
2075 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2076 : null;
2077 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2078 vers = ri.activityInfo.applicationInfo.metaData.getString(
2079 Intent.METADATA_SETUP_VERSION);
2080 }
2081 String lastVers = Settings.Secure.getString(
2082 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2083 if (vers != null && !vers.equals(lastVers)) {
2084 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2085 intent.setComponent(new ComponentName(
2086 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002087 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002088 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002089 }
2090 }
2091 }
2092 }
2093
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002094 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002095 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002096
2097 final int identHash = System.identityHashCode(r);
2098 updateUsageStats(r, true);
2099
2100 int i = mWatchers.beginBroadcast();
2101 while (i > 0) {
2102 i--;
2103 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2104 if (w != null) {
2105 try {
2106 w.activityResuming(identHash);
2107 } catch (RemoteException e) {
2108 }
2109 }
2110 }
2111 mWatchers.finishBroadcast();
2112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002114 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002115 final int N = mPendingActivityLaunches.size();
2116 if (N <= 0) {
2117 return;
2118 }
2119 for (int i=0; i<N; i++) {
2120 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002121 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002122 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2123 doResume && i == (N-1));
2124 }
2125 mPendingActivityLaunches.clear();
2126 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002127
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002128 public final int startActivity(IApplicationThread caller,
2129 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2130 int grantedMode, IBinder resultTo,
2131 String resultWho, int requestCode, boolean onlyIfNeeded,
2132 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002133 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002134 grantedUriPermissions, grantedMode, resultTo, resultWho,
2135 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002136 }
2137
2138 public final WaitResult startActivityAndWait(IApplicationThread caller,
2139 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2140 int grantedMode, IBinder resultTo,
2141 String resultWho, int requestCode, boolean onlyIfNeeded,
2142 boolean debug) {
2143 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002144 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002145 grantedUriPermissions, grantedMode, resultTo, resultWho,
2146 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002147 return res;
2148 }
2149
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002150 public final int startActivityWithConfig(IApplicationThread caller,
2151 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2152 int grantedMode, IBinder resultTo,
2153 String resultWho, int requestCode, boolean onlyIfNeeded,
2154 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002155 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002156 grantedUriPermissions, grantedMode, resultTo, resultWho,
2157 requestCode, onlyIfNeeded, debug, null, config);
2158 }
2159
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002160 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002161 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002162 IBinder resultTo, String resultWho, int requestCode,
2163 int flagsMask, int flagsValues) {
2164 // Refuse possible leaked file descriptors
2165 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2166 throw new IllegalArgumentException("File descriptors passed in Intent");
2167 }
2168
2169 IIntentSender sender = intent.getTarget();
2170 if (!(sender instanceof PendingIntentRecord)) {
2171 throw new IllegalArgumentException("Bad PendingIntent object");
2172 }
2173
2174 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002175
2176 synchronized (this) {
2177 // If this is coming from the currently resumed activity, it is
2178 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002179 if (mMainStack.mResumedActivity != null
2180 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002181 Binder.getCallingUid()) {
2182 mAppSwitchesAllowedTime = 0;
2183 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002184 }
2185
2186 return pir.sendInner(0, fillInIntent, resolvedType,
2187 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2188 }
2189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002190 public boolean startNextMatchingActivity(IBinder callingActivity,
2191 Intent intent) {
2192 // Refuse possible leaked file descriptors
2193 if (intent != null && intent.hasFileDescriptors() == true) {
2194 throw new IllegalArgumentException("File descriptors passed in Intent");
2195 }
2196
2197 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002198 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002199 if (index < 0) {
2200 return false;
2201 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002202 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 if (r.app == null || r.app.thread == null) {
2204 // The caller is not running... d'oh!
2205 return false;
2206 }
2207 intent = new Intent(intent);
2208 // The caller is not allowed to change the data.
2209 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2210 // And we are resetting to find the next component...
2211 intent.setComponent(null);
2212
2213 ActivityInfo aInfo = null;
2214 try {
2215 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002216 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002217 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002218 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002219
2220 // Look for the original activity in the list...
2221 final int N = resolves != null ? resolves.size() : 0;
2222 for (int i=0; i<N; i++) {
2223 ResolveInfo rInfo = resolves.get(i);
2224 if (rInfo.activityInfo.packageName.equals(r.packageName)
2225 && rInfo.activityInfo.name.equals(r.info.name)) {
2226 // We found the current one... the next matching is
2227 // after it.
2228 i++;
2229 if (i<N) {
2230 aInfo = resolves.get(i).activityInfo;
2231 }
2232 break;
2233 }
2234 }
2235 } catch (RemoteException e) {
2236 }
2237
2238 if (aInfo == null) {
2239 // Nobody who is next!
2240 return false;
2241 }
2242
2243 intent.setComponent(new ComponentName(
2244 aInfo.applicationInfo.packageName, aInfo.name));
2245 intent.setFlags(intent.getFlags()&~(
2246 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2247 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2248 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2249 Intent.FLAG_ACTIVITY_NEW_TASK));
2250
2251 // Okay now we need to start the new activity, replacing the
2252 // currently running activity. This is a little tricky because
2253 // we want to start the new one as if the current one is finished,
2254 // but not finish the current one first so that there is no flicker.
2255 // And thus...
2256 final boolean wasFinishing = r.finishing;
2257 r.finishing = true;
2258
2259 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002260 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002261 final String resultWho = r.resultWho;
2262 final int requestCode = r.requestCode;
2263 r.resultTo = null;
2264 if (resultTo != null) {
2265 resultTo.removeResultsLocked(r, resultWho, requestCode);
2266 }
2267
2268 final long origId = Binder.clearCallingIdentity();
2269 // XXX we are not dealing with propagating grantedUriPermissions...
2270 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002271 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002273 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 Binder.restoreCallingIdentity(origId);
2275
2276 r.finishing = wasFinishing;
2277 if (res != START_SUCCESS) {
2278 return false;
2279 }
2280 return true;
2281 }
2282 }
2283
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002284 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 Intent intent, String resolvedType, IBinder resultTo,
2286 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002287
2288 // This is so super not safe, that only the system (or okay root)
2289 // can do it.
2290 final int callingUid = Binder.getCallingUid();
2291 if (callingUid != 0 && callingUid != Process.myUid()) {
2292 throw new SecurityException(
2293 "startActivityInPackage only available to the system");
2294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002296 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2297 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2298 }
2299
2300 public final int startActivities(IApplicationThread caller,
2301 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2302 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2303 }
2304
2305 public final int startActivitiesInPackage(int uid,
2306 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2307
2308 // This is so super not safe, that only the system (or okay root)
2309 // can do it.
2310 final int callingUid = Binder.getCallingUid();
2311 if (callingUid != 0 && callingUid != Process.myUid()) {
2312 throw new SecurityException(
2313 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314 }
2315
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002316 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 }
2318
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002319 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002320 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002321 // Quick case: check if the top-most recent task is the same.
2322 if (N > 0 && mRecentTasks.get(0) == task) {
2323 return;
2324 }
2325 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002326 for (int i=0; i<N; i++) {
2327 TaskRecord tr = mRecentTasks.get(i);
2328 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2329 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2330 mRecentTasks.remove(i);
2331 i--;
2332 N--;
2333 if (task.intent == null) {
2334 // If the new recent task we are adding is not fully
2335 // specified, then replace it with the existing recent task.
2336 task = tr;
2337 }
2338 }
2339 }
2340 if (N >= MAX_RECENT_TASKS) {
2341 mRecentTasks.remove(N-1);
2342 }
2343 mRecentTasks.add(0, task);
2344 }
2345
2346 public void setRequestedOrientation(IBinder token,
2347 int requestedOrientation) {
2348 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002349 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350 if (index < 0) {
2351 return;
2352 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002353 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 final long origId = Binder.clearCallingIdentity();
2355 mWindowManager.setAppOrientation(r, requestedOrientation);
2356 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002357 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 r.mayFreezeScreenLocked(r.app) ? r : null);
2359 if (config != null) {
2360 r.frozenBeforeDestroy = true;
2361 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002362 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 }
2364 }
2365 Binder.restoreCallingIdentity(origId);
2366 }
2367 }
2368
2369 public int getRequestedOrientation(IBinder token) {
2370 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002371 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 if (index < 0) {
2373 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2374 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002375 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 return mWindowManager.getAppOrientation(r);
2377 }
2378 }
2379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 /**
2381 * This is the internal entry point for handling Activity.finish().
2382 *
2383 * @param token The Binder token referencing the Activity we want to finish.
2384 * @param resultCode Result code, if any, from this Activity.
2385 * @param resultData Result data (Intent), if any, from this Activity.
2386 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002387 * @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 -08002388 */
2389 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2390 // Refuse possible leaked file descriptors
2391 if (resultData != null && resultData.hasFileDescriptors() == true) {
2392 throw new IllegalArgumentException("File descriptors passed in Intent");
2393 }
2394
2395 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002396 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002398 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002399 if (next != null) {
2400 // ask watcher if this is allowed
2401 boolean resumeOK = true;
2402 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002403 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002404 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002405 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002406 }
2407
2408 if (!resumeOK) {
2409 return false;
2410 }
2411 }
2412 }
2413 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002414 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002415 resultData, "app-request");
2416 Binder.restoreCallingIdentity(origId);
2417 return res;
2418 }
2419 }
2420
Dianne Hackborn860755f2010-06-03 18:47:52 -07002421 public final void finishHeavyWeightApp() {
2422 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2423 != PackageManager.PERMISSION_GRANTED) {
2424 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2425 + Binder.getCallingPid()
2426 + ", uid=" + Binder.getCallingUid()
2427 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2428 Slog.w(TAG, msg);
2429 throw new SecurityException(msg);
2430 }
2431
2432 synchronized(this) {
2433 if (mHeavyWeightProcess == null) {
2434 return;
2435 }
2436
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002437 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002438 mHeavyWeightProcess.activities);
2439 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002440 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002441 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002442 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002443 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002444 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002445 null, "finish-heavy");
2446 }
2447 }
2448 }
2449
2450 mHeavyWeightProcess = null;
2451 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2452 }
2453 }
2454
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002455 public void crashApplication(int uid, int initialPid, String packageName,
2456 String message) {
2457 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2458 != PackageManager.PERMISSION_GRANTED) {
2459 String msg = "Permission Denial: crashApplication() from pid="
2460 + Binder.getCallingPid()
2461 + ", uid=" + Binder.getCallingUid()
2462 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2463 Slog.w(TAG, msg);
2464 throw new SecurityException(msg);
2465 }
2466
2467 synchronized(this) {
2468 ProcessRecord proc = null;
2469
2470 // Figure out which process to kill. We don't trust that initialPid
2471 // still has any relation to current pids, so must scan through the
2472 // list.
2473 synchronized (mPidsSelfLocked) {
2474 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2475 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2476 if (p.info.uid != uid) {
2477 continue;
2478 }
2479 if (p.pid == initialPid) {
2480 proc = p;
2481 break;
2482 }
2483 for (String str : p.pkgList) {
2484 if (str.equals(packageName)) {
2485 proc = p;
2486 }
2487 }
2488 }
2489 }
2490
2491 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002492 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002493 + " initialPid=" + initialPid
2494 + " packageName=" + packageName);
2495 return;
2496 }
2497
2498 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002499 if (proc.pid == Process.myPid()) {
2500 Log.w(TAG, "crashApplication: trying to crash self!");
2501 return;
2502 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002503 long ident = Binder.clearCallingIdentity();
2504 try {
2505 proc.thread.scheduleCrash(message);
2506 } catch (RemoteException e) {
2507 }
2508 Binder.restoreCallingIdentity(ident);
2509 }
2510 }
2511 }
2512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002513 public final void finishSubActivity(IBinder token, String resultWho,
2514 int requestCode) {
2515 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002516 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 if (index < 0) {
2518 return;
2519 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002520 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521
2522 final long origId = Binder.clearCallingIdentity();
2523
2524 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002525 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2526 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 if (r.resultTo == self && r.requestCode == requestCode) {
2528 if ((r.resultWho == null && resultWho == null) ||
2529 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002530 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002531 Activity.RESULT_CANCELED, null, "request-sub");
2532 }
2533 }
2534 }
2535
2536 Binder.restoreCallingIdentity(origId);
2537 }
2538 }
2539
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002540 public boolean willActivityBeVisible(IBinder token) {
2541 synchronized(this) {
2542 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002543 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2544 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002545 if (r == token) {
2546 return true;
2547 }
2548 if (r.fullscreen && !r.finishing) {
2549 return false;
2550 }
2551 }
2552 return true;
2553 }
2554 }
2555
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002556 public void overridePendingTransition(IBinder token, String packageName,
2557 int enterAnim, int exitAnim) {
2558 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002559 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002560 if (index < 0) {
2561 return;
2562 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002563 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002564
2565 final long origId = Binder.clearCallingIdentity();
2566
2567 if (self.state == ActivityState.RESUMED
2568 || self.state == ActivityState.PAUSING) {
2569 mWindowManager.overridePendingAppTransition(packageName,
2570 enterAnim, exitAnim);
2571 }
2572
2573 Binder.restoreCallingIdentity(origId);
2574 }
2575 }
2576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002577 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 * Main function for removing an existing process from the activity manager
2579 * as a result of that process going away. Clears out all connections
2580 * to the process.
2581 */
2582 private final void handleAppDiedLocked(ProcessRecord app,
2583 boolean restarting) {
2584 cleanUpApplicationRecordLocked(app, restarting, -1);
2585 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002586 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 }
2588
2589 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002590 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2591 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2592 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002594 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2595 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596 }
2597
2598 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002599 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600
2601 boolean atTop = true;
2602 boolean hasVisibleActivities = false;
2603
2604 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002605 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002606 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 TAG, "Removing app " + app + " from history with " + i + " entries");
2608 while (i > 0) {
2609 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002610 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002611 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002612 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2613 if (r.app == app) {
2614 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002615 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616 TAG, "Removing this entry! frozen=" + r.haveState
2617 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002618 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002619 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620
2621 r.inHistory = false;
2622 mWindowManager.removeAppToken(r);
2623 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002624 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002625 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002626 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002627
2628 } else {
2629 // We have the current state for this activity, so
2630 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002631 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 TAG, "Keeping entry, setting app to null");
2633 if (r.visible) {
2634 hasVisibleActivities = true;
2635 }
2636 r.app = null;
2637 r.nowVisible = false;
2638 if (!r.haveState) {
2639 r.icicle = null;
2640 }
2641 }
2642
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002643 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 r.state = ActivityState.STOPPED;
2645 }
2646 atTop = false;
2647 }
2648
2649 app.activities.clear();
2650
2651 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002652 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002653 + " running instrumentation " + app.instrumentationClass);
2654 Bundle info = new Bundle();
2655 info.putString("shortMsg", "Process crashed.");
2656 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2657 }
2658
2659 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002660 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 // If there was nothing to resume, and we are not already
2662 // restarting this process, but there is a visible activity that
2663 // is hosted by the process... then make sure all visible
2664 // activities are running, taking care of restarting this
2665 // process.
2666 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002667 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668 }
2669 }
2670 }
2671 }
2672
2673 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2674 IBinder threadBinder = thread.asBinder();
2675
2676 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002677 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2678 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2680 return i;
2681 }
2682 }
2683 return -1;
2684 }
2685
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002686 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002687 IApplicationThread thread) {
2688 if (thread == null) {
2689 return null;
2690 }
2691
2692 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002693 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 }
2695
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002696 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 IApplicationThread thread) {
2698
2699 mProcDeaths[0]++;
2700
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002701 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2702 synchronized (stats) {
2703 stats.noteProcessDiedLocked(app.info.uid, pid);
2704 }
2705
Magnus Edlund7bb25812010-02-24 15:45:06 +01002706 // Clean up already done if the process has been re-started.
2707 if (app.pid == pid && app.thread != null &&
2708 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002709 if (!app.killedBackground) {
2710 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2711 + ") has died.");
2712 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002713 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002714 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002715 TAG, "Dying app: " + app + ", pid: " + pid
2716 + ", thread: " + thread.asBinder());
2717 boolean doLowMem = app.instrumentationClass == null;
2718 handleAppDiedLocked(app, false);
2719
2720 if (doLowMem) {
2721 // If there are no longer any background processes running,
2722 // and the app that died was not running instrumentation,
2723 // then tell everyone we are now low on memory.
2724 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002725 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2726 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2728 haveBg = true;
2729 break;
2730 }
2731 }
2732
2733 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002734 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002735 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002736 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002737 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2738 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002739 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002740 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2741 // The low memory report is overriding any current
2742 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002743 // heavy/important/visible/foreground processes first.
2744 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002745 rec.lastRequestedGc = 0;
2746 } else {
2747 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002749 rec.reportLowMemory = true;
2750 rec.lastLowMemory = now;
2751 mProcessesToGc.remove(rec);
2752 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002753 }
2754 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002755 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002756 }
2757 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002758 } else if (app.pid != pid) {
2759 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002760 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002761 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002762 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002763 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002764 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 + thread.asBinder());
2766 }
2767 }
2768
Dan Egnor42471dd2010-01-07 17:25:22 -08002769 /**
2770 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002771 * @param clearTraces causes the dump file to be erased prior to the new
2772 * traces being written, if true; when false, the new traces will be
2773 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002774 * @param firstPids of dalvik VM processes to dump stack traces for first
2775 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002776 * @return file containing stack traces, or null if no dump file is configured
2777 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002778 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2779 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002780 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2781 if (tracesPath == null || tracesPath.length() == 0) {
2782 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002783 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002784
2785 File tracesFile = new File(tracesPath);
2786 try {
2787 File tracesDir = tracesFile.getParentFile();
2788 if (!tracesDir.exists()) tracesFile.mkdirs();
2789 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2790
Christopher Tate6ee412d2010-05-28 12:01:56 -07002791 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002792 tracesFile.createNewFile();
2793 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2794 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002795 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002796 return null;
2797 }
2798
2799 // Use a FileObserver to detect when traces finish writing.
2800 // The order of traces is considered important to maintain for legibility.
2801 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2802 public synchronized void onEvent(int event, String path) { notify(); }
2803 };
2804
2805 try {
2806 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002807
2808 // First collect all of the stacks of the most important pids.
2809 try {
2810 int num = firstPids.size();
2811 for (int i = 0; i < num; i++) {
2812 synchronized (observer) {
2813 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2814 observer.wait(200); // Wait for write-close, give up after 200msec
2815 }
2816 }
2817 } catch (InterruptedException e) {
2818 Log.wtf(TAG, e);
2819 }
2820
2821 // Next measure CPU usage.
2822 if (processStats != null) {
2823 processStats.init();
2824 System.gc();
2825 processStats.update();
2826 try {
2827 synchronized (processStats) {
2828 processStats.wait(500); // measure over 1/2 second.
2829 }
2830 } catch (InterruptedException e) {
2831 }
2832 processStats.update();
2833
2834 // We'll take the stack crawls of just the top apps using CPU.
2835 final int N = processStats.countWorkingStats();
2836 int numProcs = 0;
2837 for (int i=0; i<N && numProcs<5; i++) {
2838 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2839 if (lastPids.indexOfKey(stats.pid) >= 0) {
2840 numProcs++;
2841 try {
2842 synchronized (observer) {
2843 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2844 observer.wait(200); // Wait for write-close, give up after 200msec
2845 }
2846 } catch (InterruptedException e) {
2847 Log.wtf(TAG, e);
2848 }
2849
2850 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002851 }
2852 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002853
2854 return tracesFile;
2855
Dan Egnor42471dd2010-01-07 17:25:22 -08002856 } finally {
2857 observer.stopWatching();
2858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 }
2860
Jeff Brown4d94a762010-09-23 11:33:28 -07002861 private final class AppNotResponding implements Runnable {
2862 private final ProcessRecord mApp;
2863 private final String mAnnotation;
2864
2865 public AppNotResponding(ProcessRecord app, String annotation) {
2866 mApp = app;
2867 mAnnotation = annotation;
2868 }
2869
2870 @Override
2871 public void run() {
2872 appNotResponding(mApp, null, null, mAnnotation);
2873 }
2874 }
2875
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002876 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2877 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002878 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2879 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2880
Dianne Hackborn287952c2010-09-22 22:34:31 -07002881 if (mController != null) {
2882 try {
2883 // 0 == continue, -1 = kill process immediately
2884 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2885 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2886 } catch (RemoteException e) {
2887 mController = null;
2888 }
2889 }
2890
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002891 long anrTime = SystemClock.uptimeMillis();
2892 if (MONITOR_CPU_USAGE) {
2893 updateCpuStatsNow();
2894 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002895
2896 synchronized (this) {
2897 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2898 if (mShuttingDown) {
2899 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2900 return;
2901 } else if (app.notResponding) {
2902 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2903 return;
2904 } else if (app.crashing) {
2905 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2906 return;
2907 }
2908
2909 // In case we come through here for the same app before completing
2910 // this one, mark as anring now so we will bail out.
2911 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002912
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002913 // Log the ANR to the event log.
2914 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2915 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002916
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002917 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002918 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002919
2920 int parentPid = app.pid;
2921 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002922 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002923
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002924 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002925
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002926 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2927 ProcessRecord r = mLruProcesses.get(i);
2928 if (r != null && r.thread != null) {
2929 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002930 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2931 if (r.persistent) {
2932 firstPids.add(pid);
2933 } else {
2934 lastPids.put(pid, Boolean.TRUE);
2935 }
2936 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 }
2939 }
2940
Dan Egnor42471dd2010-01-07 17:25:22 -08002941 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002942 StringBuilder info = mStringBuilder;
2943 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002944 info.append("ANR in ").append(app.processName);
2945 if (activity != null && activity.shortComponentName != null) {
2946 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002947 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002948 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002950 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002952 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002953 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955
Dianne Hackborn287952c2010-09-22 22:34:31 -07002956 final ProcessStats processStats = new ProcessStats(true);
2957
2958 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2959
Dan Egnor42471dd2010-01-07 17:25:22 -08002960 String cpuInfo = null;
2961 if (MONITOR_CPU_USAGE) {
2962 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002963 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002964 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002965 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002966 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002967 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002968 }
2969
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002970 info.append(processStats.printCurrentState(anrTime));
2971
Joe Onorato8a9b2202010-02-26 18:56:32 -08002972 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002973 if (tracesFile == null) {
2974 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2975 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2976 }
2977
2978 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2979
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002980 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002981 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002982 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2983 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002985 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2986 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 }
2988 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002989 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 }
2991 }
2992
Dan Egnor42471dd2010-01-07 17:25:22 -08002993 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2994 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2995 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002996
2997 synchronized (this) {
2998 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2999 Process.killProcess(app.pid);
3000 return;
3001 }
3002
3003 // Set the app's notResponding state, and look up the errorReportReceiver
3004 makeAppNotRespondingLocked(app,
3005 activity != null ? activity.shortComponentName : null,
3006 annotation != null ? "ANR " + annotation : "ANR",
3007 info.toString());
3008
3009 // Bring up the infamous App Not Responding dialog
3010 Message msg = Message.obtain();
3011 HashMap map = new HashMap();
3012 msg.what = SHOW_NOT_RESPONDING_MSG;
3013 msg.obj = map;
3014 map.put("app", app);
3015 if (activity != null) {
3016 map.put("activity", activity);
3017 }
3018
3019 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 }
3022
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003023 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3024 if (!mLaunchWarningShown) {
3025 mLaunchWarningShown = true;
3026 mHandler.post(new Runnable() {
3027 @Override
3028 public void run() {
3029 synchronized (ActivityManagerService.this) {
3030 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3031 d.show();
3032 mHandler.postDelayed(new Runnable() {
3033 @Override
3034 public void run() {
3035 synchronized (ActivityManagerService.this) {
3036 d.dismiss();
3037 mLaunchWarningShown = false;
3038 }
3039 }
3040 }, 4000);
3041 }
3042 }
3043 });
3044 }
3045 }
3046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 public boolean clearApplicationUserData(final String packageName,
3048 final IPackageDataObserver observer) {
3049 int uid = Binder.getCallingUid();
3050 int pid = Binder.getCallingPid();
3051 long callingId = Binder.clearCallingIdentity();
3052 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003053 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 int pkgUid = -1;
3055 synchronized(this) {
3056 try {
3057 pkgUid = pm.getPackageUid(packageName);
3058 } catch (RemoteException e) {
3059 }
3060 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003061 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 return false;
3063 }
3064 if (uid == pkgUid || checkComponentPermission(
3065 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003066 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003067 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003068 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 } else {
3070 throw new SecurityException(pid+" does not have permission:"+
3071 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3072 "for process:"+packageName);
3073 }
3074 }
3075
3076 try {
3077 //clear application user data
3078 pm.clearApplicationUserData(packageName, observer);
3079 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3080 Uri.fromParts("package", packageName, null));
3081 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003082 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3083 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003084 } catch (RemoteException e) {
3085 }
3086 } finally {
3087 Binder.restoreCallingIdentity(callingId);
3088 }
3089 return true;
3090 }
3091
Dianne Hackborn03abb812010-01-04 18:43:19 -08003092 public void killBackgroundProcesses(final String packageName) {
3093 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3094 != PackageManager.PERMISSION_GRANTED &&
3095 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3096 != PackageManager.PERMISSION_GRANTED) {
3097 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 + Binder.getCallingPid()
3099 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003100 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003101 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 throw new SecurityException(msg);
3103 }
3104
3105 long callingId = Binder.clearCallingIdentity();
3106 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003107 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108 int pkgUid = -1;
3109 synchronized(this) {
3110 try {
3111 pkgUid = pm.getPackageUid(packageName);
3112 } catch (RemoteException e) {
3113 }
3114 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003115 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003116 return;
3117 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003118 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003119 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003120 }
3121 } finally {
3122 Binder.restoreCallingIdentity(callingId);
3123 }
3124 }
3125
3126 public void forceStopPackage(final String packageName) {
3127 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3128 != PackageManager.PERMISSION_GRANTED) {
3129 String msg = "Permission Denial: forceStopPackage() from pid="
3130 + Binder.getCallingPid()
3131 + ", uid=" + Binder.getCallingUid()
3132 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003133 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003134 throw new SecurityException(msg);
3135 }
3136
3137 long callingId = Binder.clearCallingIdentity();
3138 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003139 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003140 int pkgUid = -1;
3141 synchronized(this) {
3142 try {
3143 pkgUid = pm.getPackageUid(packageName);
3144 } catch (RemoteException e) {
3145 }
3146 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003147 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003148 return;
3149 }
3150 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003151 try {
3152 pm.setPackageStoppedState(packageName, true);
3153 } catch (RemoteException e) {
3154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003155 }
3156 } finally {
3157 Binder.restoreCallingIdentity(callingId);
3158 }
3159 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003160
3161 /*
3162 * The pkg name and uid have to be specified.
3163 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3164 */
3165 public void killApplicationWithUid(String pkg, int uid) {
3166 if (pkg == null) {
3167 return;
3168 }
3169 // Make sure the uid is valid.
3170 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003171 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003172 return;
3173 }
3174 int callerUid = Binder.getCallingUid();
3175 // Only the system server can kill an application
3176 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003177 // Post an aysnc message to kill the application
3178 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3179 msg.arg1 = uid;
3180 msg.arg2 = 0;
3181 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003182 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003183 } else {
3184 throw new SecurityException(callerUid + " cannot kill pkg: " +
3185 pkg);
3186 }
3187 }
3188
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003189 public void closeSystemDialogs(String reason) {
3190 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003191 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003192 if (reason != null) {
3193 intent.putExtra("reason", reason);
3194 }
3195
3196 final int uid = Binder.getCallingUid();
3197 final long origId = Binder.clearCallingIdentity();
3198 synchronized (this) {
3199 int i = mWatchers.beginBroadcast();
3200 while (i > 0) {
3201 i--;
3202 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3203 if (w != null) {
3204 try {
3205 w.closingSystemDialogs(reason);
3206 } catch (RemoteException e) {
3207 }
3208 }
3209 }
3210 mWatchers.finishBroadcast();
3211
Dianne Hackbornffa42482009-09-23 22:20:11 -07003212 mWindowManager.closeSystemDialogs(reason);
3213
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003214 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3215 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003216 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003217 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003218 Activity.RESULT_CANCELED, null, "close-sys");
3219 }
3220 }
3221
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003222 broadcastIntentLocked(null, null, intent, null,
3223 null, 0, null, null, null, false, false, -1, uid);
3224 }
3225 Binder.restoreCallingIdentity(origId);
3226 }
3227
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003228 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003229 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003230 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3231 for (int i=pids.length-1; i>=0; i--) {
3232 infos[i] = new Debug.MemoryInfo();
3233 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003234 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003235 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003236 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003237
3238 public void killApplicationProcess(String processName, int uid) {
3239 if (processName == null) {
3240 return;
3241 }
3242
3243 int callerUid = Binder.getCallingUid();
3244 // Only the system server can kill an application
3245 if (callerUid == Process.SYSTEM_UID) {
3246 synchronized (this) {
3247 ProcessRecord app = getProcessRecordLocked(processName, uid);
3248 if (app != null) {
3249 try {
3250 app.thread.scheduleSuicide();
3251 } catch (RemoteException e) {
3252 // If the other end already died, then our work here is done.
3253 }
3254 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003255 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003256 + processName + " / " + uid);
3257 }
3258 }
3259 } else {
3260 throw new SecurityException(callerUid + " cannot kill app process: " +
3261 processName);
3262 }
3263 }
3264
Dianne Hackborn03abb812010-01-04 18:43:19 -08003265 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003266 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3268 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003269 if (!mProcessesReady) {
3270 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003272 intent.putExtra(Intent.EXTRA_UID, uid);
3273 broadcastIntentLocked(null, null, intent,
3274 null, null, 0, null, null, null,
3275 false, false, MY_PID, Process.SYSTEM_UID);
3276 }
3277
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003278 private final boolean killPackageProcessesLocked(String packageName, int uid,
3279 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003280 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003281
Dianne Hackborn03abb812010-01-04 18:43:19 -08003282 // Remove all processes this package may have touched: all with the
3283 // same UID (except for the system or root user), and all whose name
3284 // matches the package name.
3285 final String procNamePrefix = packageName + ":";
3286 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3287 final int NA = apps.size();
3288 for (int ia=0; ia<NA; ia++) {
3289 ProcessRecord app = apps.valueAt(ia);
3290 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003291 if (doit) {
3292 procs.add(app);
3293 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003294 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3295 || app.processName.equals(packageName)
3296 || app.processName.startsWith(procNamePrefix)) {
3297 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003298 if (!doit) {
3299 return true;
3300 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003301 app.removed = true;
3302 procs.add(app);
3303 }
3304 }
3305 }
3306 }
3307
3308 int N = procs.size();
3309 for (int i=0; i<N; i++) {
3310 removeProcessLocked(procs.get(i), callerWillRestart);
3311 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003312 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003313 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003314
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003315 private final boolean forceStopPackageLocked(String name, int uid,
3316 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 int i, N;
3318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 if (uid < 0) {
3320 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003321 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003322 } catch (RemoteException e) {
3323 }
3324 }
3325
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003326 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003327 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003328
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003329 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3330 while (badApps.hasNext()) {
3331 SparseArray<Long> ba = badApps.next();
3332 if (ba.get(uid) != null) {
3333 badApps.remove();
3334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 }
3336 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003337
3338 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3339 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003341 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3342 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003344 if (!doit) {
3345 return true;
3346 }
3347 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003348 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003349 if (r.app != null) {
3350 r.app.removed = true;
3351 }
3352 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003353 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003354 }
3355 }
3356
3357 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3358 for (ServiceRecord service : mServices.values()) {
3359 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003360 if (!doit) {
3361 return true;
3362 }
3363 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003364 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 if (service.app != null) {
3366 service.app.removed = true;
3367 }
3368 service.app = null;
3369 services.add(service);
3370 }
3371 }
3372
3373 N = services.size();
3374 for (i=0; i<N; i++) {
3375 bringDownServiceLocked(services.get(i), true);
3376 }
3377
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003378 if (doit) {
3379 if (purgeCache) {
3380 AttributeCache ac = AttributeCache.instance();
3381 if (ac != null) {
3382 ac.removePackage(name);
3383 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003384 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003385 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003386 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003387
3388 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 }
3390
3391 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3392 final String name = app.processName;
3393 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003394 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 TAG, "Force removing process " + app + " (" + name
3396 + "/" + uid + ")");
3397
3398 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003399 if (mHeavyWeightProcess == app) {
3400 mHeavyWeightProcess = null;
3401 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003403 boolean needRestart = false;
3404 if (app.pid > 0 && app.pid != MY_PID) {
3405 int pid = app.pid;
3406 synchronized (mPidsSelfLocked) {
3407 mPidsSelfLocked.remove(pid);
3408 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3409 }
3410 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003411 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003412 Process.killProcess(pid);
3413
3414 if (app.persistent) {
3415 if (!callerWillRestart) {
3416 addAppLocked(app.info);
3417 } else {
3418 needRestart = true;
3419 }
3420 }
3421 } else {
3422 mRemovedProcesses.add(app);
3423 }
3424
3425 return needRestart;
3426 }
3427
3428 private final void processStartTimedOutLocked(ProcessRecord app) {
3429 final int pid = app.pid;
3430 boolean gone = false;
3431 synchronized (mPidsSelfLocked) {
3432 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3433 if (knownApp != null && knownApp.thread == null) {
3434 mPidsSelfLocked.remove(pid);
3435 gone = true;
3436 }
3437 }
3438
3439 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003440 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003441 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003442 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003443 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003444 if (mHeavyWeightProcess == app) {
3445 mHeavyWeightProcess = null;
3446 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3447 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003448 // Take care of any launching providers waiting for this process.
3449 checkAppInLaunchingProvidersLocked(app, true);
3450 // Take care of any services that are waiting for the process.
3451 for (int i=0; i<mPendingServices.size(); i++) {
3452 ServiceRecord sr = mPendingServices.get(i);
3453 if (app.info.uid == sr.appInfo.uid
3454 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003455 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003456 mPendingServices.remove(i);
3457 i--;
3458 bringDownServiceLocked(sr, true);
3459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003461 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003462 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003463 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003464 try {
3465 IBackupManager bm = IBackupManager.Stub.asInterface(
3466 ServiceManager.getService(Context.BACKUP_SERVICE));
3467 bm.agentDisconnected(app.info.packageName);
3468 } catch (RemoteException e) {
3469 // Can't happen; the backup manager is local
3470 }
3471 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003472 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003473 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003474 mPendingBroadcast.state = BroadcastRecord.IDLE;
3475 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003476 mPendingBroadcast = null;
3477 scheduleBroadcastsLocked();
3478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003480 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 }
3482 }
3483
3484 private final boolean attachApplicationLocked(IApplicationThread thread,
3485 int pid) {
3486
3487 // Find the application record that is being attached... either via
3488 // the pid if we are running in multiple processes, or just pull the
3489 // next app record if we are emulating process with anonymous threads.
3490 ProcessRecord app;
3491 if (pid != MY_PID && pid >= 0) {
3492 synchronized (mPidsSelfLocked) {
3493 app = mPidsSelfLocked.get(pid);
3494 }
3495 } else if (mStartingProcesses.size() > 0) {
3496 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003497 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498 } else {
3499 app = null;
3500 }
3501
3502 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003503 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003505 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003506 if (pid > 0 && pid != MY_PID) {
3507 Process.killProcess(pid);
3508 } else {
3509 try {
3510 thread.scheduleExit();
3511 } catch (Exception e) {
3512 // Ignore exceptions.
3513 }
3514 }
3515 return false;
3516 }
3517
3518 // If this application record is still attached to a previous
3519 // process, clean it up now.
3520 if (app.thread != null) {
3521 handleAppDiedLocked(app, true);
3522 }
3523
3524 // Tell the process all about itself.
3525
Joe Onorato8a9b2202010-02-26 18:56:32 -08003526 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003527 TAG, "Binding process pid " + pid + " to record " + app);
3528
3529 String processName = app.processName;
3530 try {
3531 thread.asBinder().linkToDeath(new AppDeathRecipient(
3532 app, pid, thread), 0);
3533 } catch (RemoteException e) {
3534 app.resetPackageList();
3535 startProcessLocked(app, "link fail", processName);
3536 return false;
3537 }
3538
Doug Zongker2bec3d42009-12-04 12:52:44 -08003539 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540
3541 app.thread = thread;
3542 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003543 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3544 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545 app.forcingToForeground = null;
3546 app.foregroundServices = false;
3547 app.debugging = false;
3548
3549 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3550
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003551 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003552 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003553
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003554 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003555 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003556 }
3557
Joe Onorato8a9b2202010-02-26 18:56:32 -08003558 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 TAG, "New app record " + app
3560 + " thread=" + thread.asBinder() + " pid=" + pid);
3561 try {
3562 int testMode = IApplicationThread.DEBUG_OFF;
3563 if (mDebugApp != null && mDebugApp.equals(processName)) {
3564 testMode = mWaitForDebugger
3565 ? IApplicationThread.DEBUG_WAIT
3566 : IApplicationThread.DEBUG_ON;
3567 app.debugging = true;
3568 if (mDebugTransient) {
3569 mDebugApp = mOrigDebugApp;
3570 mWaitForDebugger = mOrigWaitForDebugger;
3571 }
3572 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003573
Christopher Tate181fafa2009-05-14 11:12:14 -07003574 // If the app is being launched for restore or full backup, set it up specially
3575 boolean isRestrictedBackupMode = false;
3576 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3577 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3578 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3579 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003580
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003581 ensurePackageDexOpt(app.instrumentationInfo != null
3582 ? app.instrumentationInfo.packageName
3583 : app.info.packageName);
3584 if (app.instrumentationClass != null) {
3585 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003586 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003587 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003588 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003589 thread.bindApplication(processName, app.instrumentationInfo != null
3590 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 app.instrumentationClass, app.instrumentationProfileFile,
3592 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003593 isRestrictedBackupMode || !normalMode,
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003594 mConfiguration, getCommonServicesLocked(),
3595 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003596 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003597 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003598 } catch (Exception e) {
3599 // todo: Yikes! What should we do? For now we will try to
3600 // start another process, but that could easily get us in
3601 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003602 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603
3604 app.resetPackageList();
3605 startProcessLocked(app, "bind fail", processName);
3606 return false;
3607 }
3608
3609 // Remove this record from the list of starting applications.
3610 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003611 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3612 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 mProcessesOnHold.remove(app);
3614
3615 boolean badApp = false;
3616 boolean didSomething = false;
3617
3618 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003619 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003620 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3622 && processName.equals(hr.processName)) {
3623 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003624 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003625 didSomething = true;
3626 }
3627 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003628 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003629 + hr.intent.getComponent().flattenToShortString(), e);
3630 badApp = true;
3631 }
3632 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003633 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634 }
3635 }
3636
3637 // Find any services that should be running in this process...
3638 if (!badApp && mPendingServices.size() > 0) {
3639 ServiceRecord sr = null;
3640 try {
3641 for (int i=0; i<mPendingServices.size(); i++) {
3642 sr = mPendingServices.get(i);
3643 if (app.info.uid != sr.appInfo.uid
3644 || !processName.equals(sr.processName)) {
3645 continue;
3646 }
3647
3648 mPendingServices.remove(i);
3649 i--;
3650 realStartServiceLocked(sr, app);
3651 didSomething = true;
3652 }
3653 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003654 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003655 + sr.shortName, e);
3656 badApp = true;
3657 }
3658 }
3659
3660 // Check if the next broadcast receiver is in this process...
3661 BroadcastRecord br = mPendingBroadcast;
3662 if (!badApp && br != null && br.curApp == app) {
3663 try {
3664 mPendingBroadcast = null;
3665 processCurBroadcastLocked(br, app);
3666 didSomething = true;
3667 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003668 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 + br.curComponent.flattenToShortString(), e);
3670 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003671 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3673 br.resultExtras, br.resultAbort, true);
3674 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003675 // We need to reset the state if we fails to start the receiver.
3676 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003677 }
3678 }
3679
Christopher Tate181fafa2009-05-14 11:12:14 -07003680 // Check whether the next backup agent is in this process...
3681 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003682 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003683 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003684 try {
3685 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3686 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003687 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003688 e.printStackTrace();
3689 }
3690 }
3691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003692 if (badApp) {
3693 // todo: Also need to kill application to deal with all
3694 // kinds of exceptions.
3695 handleAppDiedLocked(app, false);
3696 return false;
3697 }
3698
3699 if (!didSomething) {
3700 updateOomAdjLocked();
3701 }
3702
3703 return true;
3704 }
3705
3706 public final void attachApplication(IApplicationThread thread) {
3707 synchronized (this) {
3708 int callingPid = Binder.getCallingPid();
3709 final long origId = Binder.clearCallingIdentity();
3710 attachApplicationLocked(thread, callingPid);
3711 Binder.restoreCallingIdentity(origId);
3712 }
3713 }
3714
Dianne Hackborne88846e2009-09-30 21:34:25 -07003715 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003716 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003717 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 Binder.restoreCallingIdentity(origId);
3719 }
3720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003722 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003723 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003724 mWindowManager.enableScreenAfterBoot();
3725 }
3726
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003727 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003728 IntentFilter pkgFilter = new IntentFilter();
3729 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3730 pkgFilter.addDataScheme("package");
3731 mContext.registerReceiver(new BroadcastReceiver() {
3732 @Override
3733 public void onReceive(Context context, Intent intent) {
3734 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3735 if (pkgs != null) {
3736 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003737 synchronized (ActivityManagerService.this) {
3738 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3739 setResultCode(Activity.RESULT_OK);
3740 return;
3741 }
3742 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003743 }
3744 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003745 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003746 }, pkgFilter);
3747
3748 synchronized (this) {
3749 // Ensure that any processes we had put on hold are now started
3750 // up.
3751 final int NP = mProcessesOnHold.size();
3752 if (NP > 0) {
3753 ArrayList<ProcessRecord> procs =
3754 new ArrayList<ProcessRecord>(mProcessesOnHold);
3755 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003756 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3757 + procs.get(ip));
3758 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003759 }
3760 }
3761
3762 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003763 // Start looking for apps that are abusing wake locks.
3764 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003765 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003766 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003767 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003768 broadcastIntentLocked(null, null,
3769 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3770 null, null, 0, null, null,
3771 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3772 false, false, MY_PID, Process.SYSTEM_UID);
3773 }
3774 }
3775 }
3776
3777 final void ensureBootCompleted() {
3778 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003779 boolean enableScreen;
3780 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003781 booting = mBooting;
3782 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003783 enableScreen = !mBooted;
3784 mBooted = true;
3785 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003786
3787 if (booting) {
3788 finishBooting();
3789 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003790
3791 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003792 enableScreenAfterBoot();
3793 }
3794 }
3795
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003796 public final void activityPaused(IBinder token) {
3797 final long origId = Binder.clearCallingIdentity();
3798 mMainStack.activityPaused(token, false);
3799 Binder.restoreCallingIdentity(origId);
3800 }
3801
3802 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3803 CharSequence description) {
3804 if (localLOGV) Slog.v(
3805 TAG, "Activity stopped: token=" + token);
3806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 // Refuse possible leaked file descriptors
3808 if (icicle != null && icicle.hasFileDescriptors()) {
3809 throw new IllegalArgumentException("File descriptors passed in Bundle");
3810 }
3811
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003812 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813
3814 final long origId = Binder.clearCallingIdentity();
3815
3816 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003817 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003818 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003819 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003820 r.icicle = icicle;
3821 r.haveState = true;
3822 if (thumbnail != null) {
3823 r.thumbnail = thumbnail;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003824 if (r.task != null) {
3825 r.task.lastThumbnail = r.thumbnail;
3826 }
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003828 r.description = description;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003829 if (r.task != null) {
3830 r.task.lastDescription = r.description;
3831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 r.stopped = true;
3833 r.state = ActivityState.STOPPED;
3834 if (!r.finishing) {
3835 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003836 r.stack.destroyActivityLocked(r, true);
3837 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 }
3839 }
3840 }
3841 }
3842
3843 if (r != null) {
3844 sendPendingThumbnail(r, null, null, null, false);
3845 }
3846
3847 trimApplications();
3848
3849 Binder.restoreCallingIdentity(origId);
3850 }
3851
3852 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003853 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003854 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003855 }
3856
3857 public String getCallingPackage(IBinder token) {
3858 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003859 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003860 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003861 }
3862 }
3863
3864 public ComponentName getCallingActivity(IBinder token) {
3865 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003866 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003867 return r != null ? r.intent.getComponent() : null;
3868 }
3869 }
3870
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003871 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003872 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003873 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003874 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003875 if (r != null) {
3876 return r.resultTo;
3877 }
3878 }
3879 return null;
3880 }
3881
3882 public ComponentName getActivityClassForToken(IBinder token) {
3883 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003884 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003885 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003886 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003887 return r.intent.getComponent();
3888 }
3889 return null;
3890 }
3891 }
3892
3893 public String getPackageForToken(IBinder token) {
3894 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003895 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003897 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 return r.packageName;
3899 }
3900 return null;
3901 }
3902 }
3903
3904 public IIntentSender getIntentSender(int type,
3905 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003906 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003907 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003908 if (intents != null) {
3909 if (intents.length < 1) {
3910 throw new IllegalArgumentException("Intents array length must be >= 1");
3911 }
3912 for (int i=0; i<intents.length; i++) {
3913 Intent intent = intents[i];
3914 if (intent == null) {
3915 throw new IllegalArgumentException("Null intent at index " + i);
3916 }
3917 if (intent.hasFileDescriptors()) {
3918 throw new IllegalArgumentException("File descriptors passed in Intent");
3919 }
3920 if (type == INTENT_SENDER_BROADCAST &&
3921 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3922 throw new IllegalArgumentException(
3923 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3924 }
3925 intents[i] = new Intent(intent);
3926 }
3927 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003928 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003929 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003930 }
3931 }
3932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003933 synchronized(this) {
3934 int callingUid = Binder.getCallingUid();
3935 try {
3936 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3937 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003938 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003939 .getPackageUid(packageName);
3940 if (uid != Binder.getCallingUid()) {
3941 String msg = "Permission Denial: getIntentSender() from pid="
3942 + Binder.getCallingPid()
3943 + ", uid=" + Binder.getCallingUid()
3944 + ", (need uid=" + uid + ")"
3945 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003946 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003947 throw new SecurityException(msg);
3948 }
3949 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003950
3951 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003952 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003954 } catch (RemoteException e) {
3955 throw new SecurityException(e);
3956 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003957 }
3958 }
3959
3960 IIntentSender getIntentSenderLocked(int type,
3961 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003962 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003963 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003964 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003965 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003966 if (index < 0) {
3967 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003969 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003970 if (activity.finishing) {
3971 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003973 }
3974
3975 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3976 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3977 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3978 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3979 |PendingIntent.FLAG_UPDATE_CURRENT);
3980
3981 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3982 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003983 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003984 WeakReference<PendingIntentRecord> ref;
3985 ref = mIntentSenderRecords.get(key);
3986 PendingIntentRecord rec = ref != null ? ref.get() : null;
3987 if (rec != null) {
3988 if (!cancelCurrent) {
3989 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003990 if (rec.key.requestIntent != null) {
3991 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3992 }
3993 if (intents != null) {
3994 intents[intents.length-1] = rec.key.requestIntent;
3995 rec.key.allIntents = intents;
3996 rec.key.allResolvedTypes = resolvedTypes;
3997 } else {
3998 rec.key.allIntents = null;
3999 rec.key.allResolvedTypes = null;
4000 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004002 return rec;
4003 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004004 rec.canceled = true;
4005 mIntentSenderRecords.remove(key);
4006 }
4007 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004008 return rec;
4009 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004010 rec = new PendingIntentRecord(this, key, callingUid);
4011 mIntentSenderRecords.put(key, rec.ref);
4012 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4013 if (activity.pendingResults == null) {
4014 activity.pendingResults
4015 = new HashSet<WeakReference<PendingIntentRecord>>();
4016 }
4017 activity.pendingResults.add(rec.ref);
4018 }
4019 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004020 }
4021
4022 public void cancelIntentSender(IIntentSender sender) {
4023 if (!(sender instanceof PendingIntentRecord)) {
4024 return;
4025 }
4026 synchronized(this) {
4027 PendingIntentRecord rec = (PendingIntentRecord)sender;
4028 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004029 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 .getPackageUid(rec.key.packageName);
4031 if (uid != Binder.getCallingUid()) {
4032 String msg = "Permission Denial: cancelIntentSender() from pid="
4033 + Binder.getCallingPid()
4034 + ", uid=" + Binder.getCallingUid()
4035 + " is not allowed to cancel packges "
4036 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004037 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 throw new SecurityException(msg);
4039 }
4040 } catch (RemoteException e) {
4041 throw new SecurityException(e);
4042 }
4043 cancelIntentSenderLocked(rec, true);
4044 }
4045 }
4046
4047 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4048 rec.canceled = true;
4049 mIntentSenderRecords.remove(rec.key);
4050 if (cleanActivity && rec.key.activity != null) {
4051 rec.key.activity.pendingResults.remove(rec.ref);
4052 }
4053 }
4054
4055 public String getPackageForIntentSender(IIntentSender pendingResult) {
4056 if (!(pendingResult instanceof PendingIntentRecord)) {
4057 return null;
4058 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004059 try {
4060 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4061 return res.key.packageName;
4062 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004063 }
4064 return null;
4065 }
4066
4067 public void setProcessLimit(int max) {
4068 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4069 "setProcessLimit()");
4070 mProcessLimit = max;
4071 }
4072
4073 public int getProcessLimit() {
4074 return mProcessLimit;
4075 }
4076
4077 void foregroundTokenDied(ForegroundToken token) {
4078 synchronized (ActivityManagerService.this) {
4079 synchronized (mPidsSelfLocked) {
4080 ForegroundToken cur
4081 = mForegroundProcesses.get(token.pid);
4082 if (cur != token) {
4083 return;
4084 }
4085 mForegroundProcesses.remove(token.pid);
4086 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4087 if (pr == null) {
4088 return;
4089 }
4090 pr.forcingToForeground = null;
4091 pr.foregroundServices = false;
4092 }
4093 updateOomAdjLocked();
4094 }
4095 }
4096
4097 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4098 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4099 "setProcessForeground()");
4100 synchronized(this) {
4101 boolean changed = false;
4102
4103 synchronized (mPidsSelfLocked) {
4104 ProcessRecord pr = mPidsSelfLocked.get(pid);
4105 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004106 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 return;
4108 }
4109 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4110 if (oldToken != null) {
4111 oldToken.token.unlinkToDeath(oldToken, 0);
4112 mForegroundProcesses.remove(pid);
4113 pr.forcingToForeground = null;
4114 changed = true;
4115 }
4116 if (isForeground && token != null) {
4117 ForegroundToken newToken = new ForegroundToken() {
4118 public void binderDied() {
4119 foregroundTokenDied(this);
4120 }
4121 };
4122 newToken.pid = pid;
4123 newToken.token = token;
4124 try {
4125 token.linkToDeath(newToken, 0);
4126 mForegroundProcesses.put(pid, newToken);
4127 pr.forcingToForeground = token;
4128 changed = true;
4129 } catch (RemoteException e) {
4130 // If the process died while doing this, we will later
4131 // do the cleanup with the process death link.
4132 }
4133 }
4134 }
4135
4136 if (changed) {
4137 updateOomAdjLocked();
4138 }
4139 }
4140 }
4141
4142 // =========================================================
4143 // PERMISSIONS
4144 // =========================================================
4145
4146 static class PermissionController extends IPermissionController.Stub {
4147 ActivityManagerService mActivityManagerService;
4148 PermissionController(ActivityManagerService activityManagerService) {
4149 mActivityManagerService = activityManagerService;
4150 }
4151
4152 public boolean checkPermission(String permission, int pid, int uid) {
4153 return mActivityManagerService.checkPermission(permission, pid,
4154 uid) == PackageManager.PERMISSION_GRANTED;
4155 }
4156 }
4157
4158 /**
4159 * This can be called with or without the global lock held.
4160 */
4161 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004162 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004163 // We might be performing an operation on behalf of an indirect binder
4164 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4165 // client identity accordingly before proceeding.
4166 Identity tlsIdentity = sCallerIdentity.get();
4167 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004168 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4170 uid = tlsIdentity.uid;
4171 pid = tlsIdentity.pid;
4172 }
4173
4174 // Root, system server and our own process get to do everything.
4175 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4176 !Process.supportsProcesses()) {
4177 return PackageManager.PERMISSION_GRANTED;
4178 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004179 // If there is a uid that owns whatever is being accessed, it has
4180 // blanket access to it regardless of the permissions it requires.
4181 if (owningUid >= 0 && uid == owningUid) {
4182 return PackageManager.PERMISSION_GRANTED;
4183 }
4184 // If the target is not exported, then nobody else can get to it.
4185 if (!exported) {
4186 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004187 return PackageManager.PERMISSION_DENIED;
4188 }
4189 if (permission == null) {
4190 return PackageManager.PERMISSION_GRANTED;
4191 }
4192 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004193 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 .checkUidPermission(permission, uid);
4195 } catch (RemoteException e) {
4196 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004197 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004198 }
4199 return PackageManager.PERMISSION_DENIED;
4200 }
4201
4202 /**
4203 * As the only public entry point for permissions checking, this method
4204 * can enforce the semantic that requesting a check on a null global
4205 * permission is automatically denied. (Internally a null permission
4206 * string is used when calling {@link #checkComponentPermission} in cases
4207 * when only uid-based security is needed.)
4208 *
4209 * This can be called with or without the global lock held.
4210 */
4211 public int checkPermission(String permission, int pid, int uid) {
4212 if (permission == null) {
4213 return PackageManager.PERMISSION_DENIED;
4214 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004215 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004216 }
4217
4218 /**
4219 * Binder IPC calls go through the public entry point.
4220 * This can be called with or without the global lock held.
4221 */
4222 int checkCallingPermission(String permission) {
4223 return checkPermission(permission,
4224 Binder.getCallingPid(),
4225 Binder.getCallingUid());
4226 }
4227
4228 /**
4229 * This can be called with or without the global lock held.
4230 */
4231 void enforceCallingPermission(String permission, String func) {
4232 if (checkCallingPermission(permission)
4233 == PackageManager.PERMISSION_GRANTED) {
4234 return;
4235 }
4236
4237 String msg = "Permission Denial: " + func + " from pid="
4238 + Binder.getCallingPid()
4239 + ", uid=" + Binder.getCallingUid()
4240 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004241 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 throw new SecurityException(msg);
4243 }
4244
4245 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004246 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4247 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4248 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4249 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4250 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004251 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004252 // Is the component private from the target uid?
4253 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4254
4255 // Acceptable if the there is no read permission needed from the
4256 // target or the target is holding the read permission.
4257 if (!readPerm) {
4258 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004260 == PackageManager.PERMISSION_GRANTED)) {
4261 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004262 }
4263 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004264
4265 // Acceptable if the there is no write permission needed from the
4266 // target or the target is holding the read permission.
4267 if (!writePerm) {
4268 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004270 == PackageManager.PERMISSION_GRANTED)) {
4271 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 }
4273 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004274
4275 // Acceptable if there is a path permission matching the URI that
4276 // the target holds the permission on.
4277 PathPermission[] pps = pi.pathPermissions;
4278 if (pps != null && (!readPerm || !writePerm)) {
4279 final String path = uri.getPath();
4280 int i = pps.length;
4281 while (i > 0 && (!readPerm || !writePerm)) {
4282 i--;
4283 PathPermission pp = pps[i];
4284 if (!readPerm) {
4285 final String pprperm = pp.getReadPermission();
4286 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4287 + pprperm + " for " + pp.getPath()
4288 + ": match=" + pp.match(path)
4289 + " check=" + pm.checkUidPermission(pprperm, uid));
4290 if (pprperm != null && pp.match(path) &&
4291 (pm.checkUidPermission(pprperm, uid)
4292 == PackageManager.PERMISSION_GRANTED)) {
4293 readPerm = true;
4294 }
4295 }
4296 if (!writePerm) {
4297 final String ppwperm = pp.getWritePermission();
4298 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4299 + ppwperm + " for " + pp.getPath()
4300 + ": match=" + pp.match(path)
4301 + " check=" + pm.checkUidPermission(ppwperm, uid));
4302 if (ppwperm != null && pp.match(path) &&
4303 (pm.checkUidPermission(ppwperm, uid)
4304 == PackageManager.PERMISSION_GRANTED)) {
4305 writePerm = true;
4306 }
4307 }
4308 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 } catch (RemoteException e) {
4311 return false;
4312 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004313
4314 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004315 }
4316
4317 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4318 int modeFlags) {
4319 // Root gets to do everything.
4320 if (uid == 0 || !Process.supportsProcesses()) {
4321 return true;
4322 }
4323 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4324 if (perms == null) return false;
4325 UriPermission perm = perms.get(uri);
4326 if (perm == null) return false;
4327 return (modeFlags&perm.modeFlags) == modeFlags;
4328 }
4329
4330 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4331 // Another redirected-binder-call permissions check as in
4332 // {@link checkComponentPermission}.
4333 Identity tlsIdentity = sCallerIdentity.get();
4334 if (tlsIdentity != null) {
4335 uid = tlsIdentity.uid;
4336 pid = tlsIdentity.pid;
4337 }
4338
4339 // Our own process gets to do everything.
4340 if (pid == MY_PID) {
4341 return PackageManager.PERMISSION_GRANTED;
4342 }
4343 synchronized(this) {
4344 return checkUriPermissionLocked(uri, uid, modeFlags)
4345 ? PackageManager.PERMISSION_GRANTED
4346 : PackageManager.PERMISSION_DENIED;
4347 }
4348 }
4349
Dianne Hackborn39792d22010-08-19 18:01:52 -07004350 /**
4351 * Check if the targetPkg can be granted permission to access uri by
4352 * the callingUid using the given modeFlags. Throws a security exception
4353 * if callingUid is not allowed to do this. Returns the uid of the target
4354 * if the URI permission grant should be performed; returns -1 if it is not
4355 * needed (for example targetPkg already has permission to access the URI).
4356 */
4357 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4358 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004359 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4360 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4361 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004362 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 }
4364
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004365 if (targetPkg != null) {
4366 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4367 "Checking grant " + targetPkg + " permission to " + uri);
4368 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004369
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004370 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004371
4372 // If this is not a content: uri, we can't do anything with it.
4373 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004374 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004375 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004376 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004377 }
4378
4379 String name = uri.getAuthority();
4380 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004381 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004382 if (cpr != null) {
4383 pi = cpr.info;
4384 } else {
4385 try {
4386 pi = pm.resolveContentProvider(name,
4387 PackageManager.GET_URI_PERMISSION_PATTERNS);
4388 } catch (RemoteException ex) {
4389 }
4390 }
4391 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004392 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004393 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 }
4395
4396 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004397 if (targetPkg != null) {
4398 try {
4399 targetUid = pm.getPackageUid(targetPkg);
4400 if (targetUid < 0) {
4401 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4402 "Can't grant URI permission no uid for: " + targetPkg);
4403 return -1;
4404 }
4405 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004406 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004407 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004408 } else {
4409 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 }
4411
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004412 if (targetUid >= 0) {
4413 // First... does the target actually need this permission?
4414 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4415 // No need to grant the target this permission.
4416 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4417 "Target " + targetPkg + " already has full permission to " + uri);
4418 return -1;
4419 }
4420 } else {
4421 // First... there is no target package, so can anyone access it?
4422 boolean allowed = pi.exported;
4423 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4424 if (pi.readPermission != null) {
4425 allowed = false;
4426 }
4427 }
4428 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4429 if (pi.writePermission != null) {
4430 allowed = false;
4431 }
4432 }
4433 if (allowed) {
4434 return -1;
4435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 }
4437
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004438 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004439 if (!pi.grantUriPermissions) {
4440 throw new SecurityException("Provider " + pi.packageName
4441 + "/" + pi.name
4442 + " does not allow granting of Uri permissions (uri "
4443 + uri + ")");
4444 }
4445 if (pi.uriPermissionPatterns != null) {
4446 final int N = pi.uriPermissionPatterns.length;
4447 boolean allowed = false;
4448 for (int i=0; i<N; i++) {
4449 if (pi.uriPermissionPatterns[i] != null
4450 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4451 allowed = true;
4452 break;
4453 }
4454 }
4455 if (!allowed) {
4456 throw new SecurityException("Provider " + pi.packageName
4457 + "/" + pi.name
4458 + " does not allow granting of permission to path of Uri "
4459 + uri);
4460 }
4461 }
4462
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004463 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004464 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004465 if (callingUid != Process.myUid()) {
4466 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4467 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4468 throw new SecurityException("Uid " + callingUid
4469 + " does not have permission to uri " + uri);
4470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004471 }
4472 }
4473
Dianne Hackborn39792d22010-08-19 18:01:52 -07004474 return targetUid;
4475 }
4476
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004477 public int checkGrantUriPermission(int callingUid, String targetPkg,
4478 Uri uri, int modeFlags) {
4479 synchronized(this) {
4480 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4481 }
4482 }
4483
Dianne Hackborn39792d22010-08-19 18:01:52 -07004484 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4485 Uri uri, int modeFlags, UriPermissionOwner owner) {
4486 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4487 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4488 if (modeFlags == 0) {
4489 return;
4490 }
4491
4492 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 // to the uri, and the target doesn't. Let's now give this to
4494 // the target.
4495
Joe Onorato8a9b2202010-02-26 18:56:32 -08004496 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004497 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004499 HashMap<Uri, UriPermission> targetUris
4500 = mGrantedUriPermissions.get(targetUid);
4501 if (targetUris == null) {
4502 targetUris = new HashMap<Uri, UriPermission>();
4503 mGrantedUriPermissions.put(targetUid, targetUris);
4504 }
4505
4506 UriPermission perm = targetUris.get(uri);
4507 if (perm == null) {
4508 perm = new UriPermission(targetUid, uri);
4509 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004512 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004513 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004514 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004515 } else {
4516 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4517 perm.readOwners.add(owner);
4518 owner.addReadPermission(perm);
4519 }
4520 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4521 perm.writeOwners.add(owner);
4522 owner.addWritePermission(perm);
4523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 }
4525 }
4526
Dianne Hackborn39792d22010-08-19 18:01:52 -07004527 void grantUriPermissionLocked(int callingUid,
4528 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004529 if (targetPkg == null) {
4530 throw new NullPointerException("targetPkg");
4531 }
4532
Dianne Hackborn39792d22010-08-19 18:01:52 -07004533 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4534 if (targetUid < 0) {
4535 return;
4536 }
4537
4538 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4539 }
4540
4541 /**
4542 * Like checkGrantUriPermissionLocked, but takes an Intent.
4543 */
4544 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4545 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004546 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004547 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004548 + " from " + intent + "; flags=0x"
4549 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4550
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004551 if (targetPkg == null) {
4552 throw new NullPointerException("targetPkg");
4553 }
4554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004555 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004556 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004557 }
4558 Uri data = intent.getData();
4559 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004560 return -1;
4561 }
4562 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4563 intent.getFlags());
4564 }
4565
4566 /**
4567 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4568 */
4569 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4570 String targetPkg, Intent intent, UriPermissionOwner owner) {
4571 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4572 intent.getFlags(), owner);
4573 }
4574
4575 void grantUriPermissionFromIntentLocked(int callingUid,
4576 String targetPkg, Intent intent, UriPermissionOwner owner) {
4577 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4578 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 return;
4580 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004581
4582 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004583 }
4584
4585 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4586 Uri uri, int modeFlags) {
4587 synchronized(this) {
4588 final ProcessRecord r = getRecordForAppLocked(caller);
4589 if (r == null) {
4590 throw new SecurityException("Unable to find app for caller "
4591 + caller
4592 + " when granting permission to uri " + uri);
4593 }
4594 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004595 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004596 }
4597 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004598 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 }
4600
4601 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4602 null);
4603 }
4604 }
4605
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004606 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4608 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4609 HashMap<Uri, UriPermission> perms
4610 = mGrantedUriPermissions.get(perm.uid);
4611 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004612 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004613 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004614 perms.remove(perm.uri);
4615 if (perms.size() == 0) {
4616 mGrantedUriPermissions.remove(perm.uid);
4617 }
4618 }
4619 }
4620 }
4621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004622 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4623 int modeFlags) {
4624 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4625 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4626 if (modeFlags == 0) {
4627 return;
4628 }
4629
Joe Onorato8a9b2202010-02-26 18:56:32 -08004630 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004631 "Revoking all granted permissions to " + uri);
4632
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004633 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634
4635 final String authority = uri.getAuthority();
4636 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004637 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004638 if (cpr != null) {
4639 pi = cpr.info;
4640 } else {
4641 try {
4642 pi = pm.resolveContentProvider(authority,
4643 PackageManager.GET_URI_PERMISSION_PATTERNS);
4644 } catch (RemoteException ex) {
4645 }
4646 }
4647 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004648 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004649 return;
4650 }
4651
4652 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004653 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004654 // Right now, if you are not the original owner of the permission,
4655 // you are not allowed to revoke it.
4656 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4657 throw new SecurityException("Uid " + callingUid
4658 + " does not have permission to uri " + uri);
4659 //}
4660 }
4661
4662 // Go through all of the permissions and remove any that match.
4663 final List<String> SEGMENTS = uri.getPathSegments();
4664 if (SEGMENTS != null) {
4665 final int NS = SEGMENTS.size();
4666 int N = mGrantedUriPermissions.size();
4667 for (int i=0; i<N; i++) {
4668 HashMap<Uri, UriPermission> perms
4669 = mGrantedUriPermissions.valueAt(i);
4670 Iterator<UriPermission> it = perms.values().iterator();
4671 toploop:
4672 while (it.hasNext()) {
4673 UriPermission perm = it.next();
4674 Uri targetUri = perm.uri;
4675 if (!authority.equals(targetUri.getAuthority())) {
4676 continue;
4677 }
4678 List<String> targetSegments = targetUri.getPathSegments();
4679 if (targetSegments == null) {
4680 continue;
4681 }
4682 if (targetSegments.size() < NS) {
4683 continue;
4684 }
4685 for (int j=0; j<NS; j++) {
4686 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4687 continue toploop;
4688 }
4689 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004690 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004691 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004692 perm.clearModes(modeFlags);
4693 if (perm.modeFlags == 0) {
4694 it.remove();
4695 }
4696 }
4697 if (perms.size() == 0) {
4698 mGrantedUriPermissions.remove(
4699 mGrantedUriPermissions.keyAt(i));
4700 N--;
4701 i--;
4702 }
4703 }
4704 }
4705 }
4706
4707 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4708 int modeFlags) {
4709 synchronized(this) {
4710 final ProcessRecord r = getRecordForAppLocked(caller);
4711 if (r == null) {
4712 throw new SecurityException("Unable to find app for caller "
4713 + caller
4714 + " when revoking permission to uri " + uri);
4715 }
4716 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004717 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004718 return;
4719 }
4720
4721 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4722 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4723 if (modeFlags == 0) {
4724 return;
4725 }
4726
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004727 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004728
4729 final String authority = uri.getAuthority();
4730 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004731 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 if (cpr != null) {
4733 pi = cpr.info;
4734 } else {
4735 try {
4736 pi = pm.resolveContentProvider(authority,
4737 PackageManager.GET_URI_PERMISSION_PATTERNS);
4738 } catch (RemoteException ex) {
4739 }
4740 }
4741 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004742 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004743 return;
4744 }
4745
4746 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4747 }
4748 }
4749
Dianne Hackborn7e269642010-08-25 19:50:20 -07004750 @Override
4751 public IBinder newUriPermissionOwner(String name) {
4752 synchronized(this) {
4753 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4754 return owner.getExternalTokenLocked();
4755 }
4756 }
4757
4758 @Override
4759 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4760 Uri uri, int modeFlags) {
4761 synchronized(this) {
4762 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4763 if (owner == null) {
4764 throw new IllegalArgumentException("Unknown owner: " + token);
4765 }
4766 if (fromUid != Binder.getCallingUid()) {
4767 if (Binder.getCallingUid() != Process.myUid()) {
4768 // Only system code can grant URI permissions on behalf
4769 // of other users.
4770 throw new SecurityException("nice try");
4771 }
4772 }
4773 if (targetPkg == null) {
4774 throw new IllegalArgumentException("null target");
4775 }
4776 if (uri == null) {
4777 throw new IllegalArgumentException("null uri");
4778 }
4779
4780 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4781 }
4782 }
4783
4784 @Override
4785 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4786 synchronized(this) {
4787 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4788 if (owner == null) {
4789 throw new IllegalArgumentException("Unknown owner: " + token);
4790 }
4791
4792 if (uri == null) {
4793 owner.removeUriPermissionsLocked(mode);
4794 } else {
4795 owner.removeUriPermissionLocked(uri, mode);
4796 }
4797 }
4798 }
4799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4801 synchronized (this) {
4802 ProcessRecord app =
4803 who != null ? getRecordForAppLocked(who) : null;
4804 if (app == null) return;
4805
4806 Message msg = Message.obtain();
4807 msg.what = WAIT_FOR_DEBUGGER_MSG;
4808 msg.obj = app;
4809 msg.arg1 = waiting ? 1 : 0;
4810 mHandler.sendMessage(msg);
4811 }
4812 }
4813
4814 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4815 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004816 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004817 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004818 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004819 }
4820
4821 // =========================================================
4822 // TASK MANAGEMENT
4823 // =========================================================
4824
4825 public List getTasks(int maxNum, int flags,
4826 IThumbnailReceiver receiver) {
4827 ArrayList list = new ArrayList();
4828
4829 PendingThumbnailsRecord pending = null;
4830 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004831 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832
4833 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004834 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4836 + ", receiver=" + receiver);
4837
4838 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4839 != PackageManager.PERMISSION_GRANTED) {
4840 if (receiver != null) {
4841 // If the caller wants to wait for pending thumbnails,
4842 // it ain't gonna get them.
4843 try {
4844 receiver.finished();
4845 } catch (RemoteException ex) {
4846 }
4847 }
4848 String msg = "Permission Denial: getTasks() from pid="
4849 + Binder.getCallingPid()
4850 + ", uid=" + Binder.getCallingUid()
4851 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004852 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 throw new SecurityException(msg);
4854 }
4855
Dianne Hackbornd2835932010-12-13 16:28:46 -08004856 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4857 && checkCallingPermission(
4858 android.Manifest.permission.READ_FRAME_BUFFER)
4859 == PackageManager.PERMISSION_GRANTED;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004860
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004861 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004862 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004863 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004864 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 CharSequence topDescription = null;
4866 TaskRecord curTask = null;
4867 int numActivities = 0;
4868 int numRunning = 0;
4869 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004870 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004871 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004872 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004873
4874 // Initialize state for next task if needed.
4875 if (top == null ||
4876 (top.state == ActivityState.INITIALIZING
4877 && top.task == r.task)) {
4878 top = r;
4879 topDescription = r.description;
4880 curTask = r.task;
4881 numActivities = numRunning = 0;
4882 }
4883
4884 // Add 'r' into the current task.
4885 numActivities++;
4886 if (r.app != null && r.app.thread != null) {
4887 numRunning++;
4888 }
4889 if (topDescription == null) {
4890 topDescription = r.description;
4891 }
4892
Joe Onorato8a9b2202010-02-26 18:56:32 -08004893 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004894 TAG, r.intent.getComponent().flattenToShortString()
4895 + ": task=" + r.task);
4896
4897 // If the next one is a different task, generate a new
4898 // TaskInfo entry for what we have.
4899 if (next == null || next.task != curTask) {
4900 ActivityManager.RunningTaskInfo ci
4901 = new ActivityManager.RunningTaskInfo();
4902 ci.id = curTask.taskId;
4903 ci.baseActivity = r.intent.getComponent();
4904 ci.topActivity = top.intent.getComponent();
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004905 if (canReadFb) {
4906 if (top.thumbnail != null) {
4907 ci.thumbnail = top.thumbnail;
4908 } else if (top.state == ActivityState.RESUMED) {
Dianne Hackbornd2835932010-12-13 16:28:46 -08004909 ci.thumbnail = top.stack.screenshotActivities(top);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004910 }
4911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 ci.description = topDescription;
4913 ci.numActivities = numActivities;
4914 ci.numRunning = numRunning;
4915 //System.out.println(
4916 // "#" + maxNum + ": " + " descr=" + ci.description);
4917 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004918 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004919 TAG, "State=" + top.state + "Idle=" + top.idle
4920 + " app=" + top.app
4921 + " thr=" + (top.app != null ? top.app.thread : null));
4922 if (top.state == ActivityState.RESUMED
4923 || top.state == ActivityState.PAUSING) {
4924 if (top.idle && top.app != null
4925 && top.app.thread != null) {
4926 topRecord = top;
4927 topThumbnail = top.app.thread;
4928 } else {
4929 top.thumbnailNeeded = true;
4930 }
4931 }
4932 if (pending == null) {
4933 pending = new PendingThumbnailsRecord(receiver);
4934 }
4935 pending.pendingRecords.add(top);
4936 }
4937 list.add(ci);
4938 maxNum--;
4939 top = null;
4940 }
4941 }
4942
4943 if (pending != null) {
4944 mPendingThumbnails.add(pending);
4945 }
4946 }
4947
Joe Onorato8a9b2202010-02-26 18:56:32 -08004948 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949
4950 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004951 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 try {
4953 topThumbnail.requestThumbnail(topRecord);
4954 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004955 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004956 sendPendingThumbnail(null, topRecord, null, null, true);
4957 }
4958 }
4959
4960 if (pending == null && receiver != null) {
4961 // In this case all thumbnails were available and the client
4962 // is being asked to be told when the remaining ones come in...
4963 // which is unusually, since the top-most currently running
4964 // activity should never have a canned thumbnail! Oh well.
4965 try {
4966 receiver.finished();
4967 } catch (RemoteException ex) {
4968 }
4969 }
4970
4971 return list;
4972 }
4973
4974 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4975 int flags) {
4976 synchronized (this) {
4977 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4978 "getRecentTasks()");
4979
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004980 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004981
Dianne Hackbornd2835932010-12-13 16:28:46 -08004982 ActivityRecord resumed = mMainStack.mResumedActivity;
4983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004984 final int N = mRecentTasks.size();
4985 ArrayList<ActivityManager.RecentTaskInfo> res
4986 = new ArrayList<ActivityManager.RecentTaskInfo>(
4987 maxNum < N ? maxNum : N);
4988 for (int i=0; i<N && maxNum > 0; i++) {
4989 TaskRecord tr = mRecentTasks.get(i);
4990 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4991 || (tr.intent == null)
4992 || ((tr.intent.getFlags()
4993 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4994 ActivityManager.RecentTaskInfo rti
4995 = new ActivityManager.RecentTaskInfo();
4996 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08004997 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004998 rti.baseIntent = new Intent(
4999 tr.intent != null ? tr.intent : tr.affinityIntent);
5000 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005001 rti.description = tr.lastDescription;
5002
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005003 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5004 // Check whether this activity is currently available.
5005 try {
5006 if (rti.origActivity != null) {
5007 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5008 continue;
5009 }
5010 } else if (rti.baseIntent != null) {
5011 if (pm.queryIntentActivities(rti.baseIntent,
5012 null, 0) == null) {
5013 continue;
5014 }
5015 }
5016 } catch (RemoteException e) {
5017 // Will never happen.
5018 }
5019 }
5020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005021 res.add(rti);
5022 maxNum--;
5023 }
5024 }
5025 return res;
5026 }
5027 }
5028
Dianne Hackbornd94df452011-02-16 18:53:31 -08005029 public Bitmap getTaskThumbnail(int id) {
5030 synchronized (this) {
5031 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5032 "getTaskThumbnail()");
5033 ActivityRecord resumed = mMainStack.mResumedActivity;
5034 final int N = mRecentTasks.size();
5035 for (int i=0; i<N; i++) {
5036 TaskRecord tr = mRecentTasks.get(i);
5037 if (tr.taskId == id) {
5038 if (resumed != null && resumed.task == tr) {
5039 return resumed.stack.screenshotActivities(resumed);
5040 } else {
5041 return tr.lastThumbnail;
5042 }
5043 }
5044 }
5045 }
5046 return null;
5047 }
5048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5050 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005051 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005052 TaskRecord jt = startTask;
5053
5054 // First look backwards
5055 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005056 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005057 if (r.task != jt) {
5058 jt = r.task;
5059 if (affinity.equals(jt.affinity)) {
5060 return j;
5061 }
5062 }
5063 }
5064
5065 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005066 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005067 jt = startTask;
5068 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005069 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005070 if (r.task != jt) {
5071 if (affinity.equals(jt.affinity)) {
5072 return j;
5073 }
5074 jt = r.task;
5075 }
5076 }
5077
5078 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005079 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005080 return N-1;
5081 }
5082
5083 return -1;
5084 }
5085
5086 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005087 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005088 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005089 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5091 "moveTaskToFront()");
5092
5093 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005094 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5095 Binder.getCallingUid(), "Task to front")) {
5096 return;
5097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005098 final long origId = Binder.clearCallingIdentity();
5099 try {
5100 int N = mRecentTasks.size();
5101 for (int i=0; i<N; i++) {
5102 TaskRecord tr = mRecentTasks.get(i);
5103 if (tr.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005104 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5105 mMainStack.mUserLeaving = true;
5106 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005107 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5108 // Caller wants the home activity moved with it. To accomplish this,
5109 // we'll just move the home task to the top first.
5110 mMainStack.moveHomeToFrontLocked();
5111 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005112 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113 return;
5114 }
5115 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005116 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5117 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005118 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005119 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5120 mMainStack.mUserLeaving = true;
5121 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005122 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5123 // Caller wants the home activity moved with it. To accomplish this,
5124 // we'll just move the home task to the top first.
5125 mMainStack.moveHomeToFrontLocked();
5126 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005127 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 return;
5129 }
5130 }
5131 } finally {
5132 Binder.restoreCallingIdentity(origId);
5133 }
5134 }
5135 }
5136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005137 public void moveTaskToBack(int task) {
5138 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5139 "moveTaskToBack()");
5140
5141 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005142 if (mMainStack.mResumedActivity != null
5143 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005144 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5145 Binder.getCallingUid(), "Task to back")) {
5146 return;
5147 }
5148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005150 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005151 Binder.restoreCallingIdentity(origId);
5152 }
5153 }
5154
5155 /**
5156 * Moves an activity, and all of the other activities within the same task, to the bottom
5157 * of the history stack. The activity's order within the task is unchanged.
5158 *
5159 * @param token A reference to the activity we wish to move
5160 * @param nonRoot If false then this only works if the activity is the root
5161 * of a task; if true it will work for any activity in a task.
5162 * @return Returns true if the move completed, false if not.
5163 */
5164 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5165 synchronized(this) {
5166 final long origId = Binder.clearCallingIdentity();
5167 int taskId = getTaskForActivityLocked(token, !nonRoot);
5168 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005169 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005170 }
5171 Binder.restoreCallingIdentity(origId);
5172 }
5173 return false;
5174 }
5175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005176 public void moveTaskBackwards(int task) {
5177 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5178 "moveTaskBackwards()");
5179
5180 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005181 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5182 Binder.getCallingUid(), "Task backwards")) {
5183 return;
5184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005185 final long origId = Binder.clearCallingIdentity();
5186 moveTaskBackwardsLocked(task);
5187 Binder.restoreCallingIdentity(origId);
5188 }
5189 }
5190
5191 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005192 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193 }
5194
5195 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5196 synchronized(this) {
5197 return getTaskForActivityLocked(token, onlyRoot);
5198 }
5199 }
5200
5201 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005202 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203 TaskRecord lastTask = null;
5204 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005205 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 if (r == token) {
5207 if (!onlyRoot || lastTask != r.task) {
5208 return r.task.taskId;
5209 }
5210 return -1;
5211 }
5212 lastTask = r.task;
5213 }
5214
5215 return -1;
5216 }
5217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218 public void finishOtherInstances(IBinder token, ComponentName className) {
5219 synchronized(this) {
5220 final long origId = Binder.clearCallingIdentity();
5221
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005222 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223 TaskRecord lastTask = null;
5224 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005225 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005226 if (r.realActivity.equals(className)
5227 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005228 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005229 null, "others")) {
5230 i--;
5231 N--;
5232 }
5233 }
5234 lastTask = r.task;
5235 }
5236
5237 Binder.restoreCallingIdentity(origId);
5238 }
5239 }
5240
5241 // =========================================================
5242 // THUMBNAILS
5243 // =========================================================
5244
5245 public void reportThumbnail(IBinder token,
5246 Bitmap thumbnail, CharSequence description) {
5247 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5248 final long origId = Binder.clearCallingIdentity();
5249 sendPendingThumbnail(null, token, thumbnail, description, true);
5250 Binder.restoreCallingIdentity(origId);
5251 }
5252
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005253 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 Bitmap thumbnail, CharSequence description, boolean always) {
5255 TaskRecord task = null;
5256 ArrayList receivers = null;
5257
5258 //System.out.println("Send pending thumbnail: " + r);
5259
5260 synchronized(this) {
5261 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005262 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 if (index < 0) {
5264 return;
5265 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005266 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005267 }
5268 if (thumbnail == null) {
5269 thumbnail = r.thumbnail;
5270 description = r.description;
5271 }
5272 if (thumbnail == null && !always) {
5273 // If there is no thumbnail, and this entry is not actually
5274 // going away, then abort for now and pick up the next
5275 // thumbnail we get.
5276 return;
5277 }
5278 task = r.task;
5279
5280 int N = mPendingThumbnails.size();
5281 int i=0;
5282 while (i<N) {
5283 PendingThumbnailsRecord pr =
5284 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5285 //System.out.println("Looking in " + pr.pendingRecords);
5286 if (pr.pendingRecords.remove(r)) {
5287 if (receivers == null) {
5288 receivers = new ArrayList();
5289 }
5290 receivers.add(pr);
5291 if (pr.pendingRecords.size() == 0) {
5292 pr.finished = true;
5293 mPendingThumbnails.remove(i);
5294 N--;
5295 continue;
5296 }
5297 }
5298 i++;
5299 }
5300 }
5301
5302 if (receivers != null) {
5303 final int N = receivers.size();
5304 for (int i=0; i<N; i++) {
5305 try {
5306 PendingThumbnailsRecord pr =
5307 (PendingThumbnailsRecord)receivers.get(i);
5308 pr.receiver.newThumbnail(
5309 task != null ? task.taskId : -1, thumbnail, description);
5310 if (pr.finished) {
5311 pr.receiver.finished();
5312 }
5313 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005314 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005315 }
5316 }
5317 }
5318 }
5319
5320 // =========================================================
5321 // CONTENT PROVIDERS
5322 // =========================================================
5323
5324 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5325 List providers = null;
5326 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005327 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005328 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005329 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 } catch (RemoteException ex) {
5331 }
5332 if (providers != null) {
5333 final int N = providers.size();
5334 for (int i=0; i<N; i++) {
5335 ProviderInfo cpi =
5336 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005337 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338 if (cpr == null) {
5339 cpr = new ContentProviderRecord(cpi, app.info);
5340 mProvidersByClass.put(cpi.name, cpr);
5341 }
5342 app.pubProviders.put(cpi.name, cpr);
5343 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005344 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 }
5346 }
5347 return providers;
5348 }
5349
5350 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005351 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005352 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5353 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5354 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005355 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005356 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 return null;
5358 }
5359 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005360 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005361 == PackageManager.PERMISSION_GRANTED) {
5362 return null;
5363 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005364
5365 PathPermission[] pps = cpi.pathPermissions;
5366 if (pps != null) {
5367 int i = pps.length;
5368 while (i > 0) {
5369 i--;
5370 PathPermission pp = pps[i];
5371 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005372 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005373 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005374 return null;
5375 }
5376 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005377 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005378 == PackageManager.PERMISSION_GRANTED) {
5379 return null;
5380 }
5381 }
5382 }
5383
Dianne Hackbornb424b632010-08-18 15:59:05 -07005384 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5385 if (perms != null) {
5386 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5387 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5388 return null;
5389 }
5390 }
5391 }
5392
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005393 String msg;
5394 if (!cpi.exported) {
5395 msg = "Permission Denial: opening provider " + cpi.name
5396 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5397 + ", uid=" + callingUid + ") that is not exported from uid "
5398 + cpi.applicationInfo.uid;
5399 } else {
5400 msg = "Permission Denial: opening provider " + cpi.name
5401 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5402 + ", uid=" + callingUid + ") requires "
5403 + cpi.readPermission + " or " + cpi.writePermission;
5404 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005405 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005406 return msg;
5407 }
5408
5409 private final ContentProviderHolder getContentProviderImpl(
5410 IApplicationThread caller, String name) {
5411 ContentProviderRecord cpr;
5412 ProviderInfo cpi = null;
5413
5414 synchronized(this) {
5415 ProcessRecord r = null;
5416 if (caller != null) {
5417 r = getRecordForAppLocked(caller);
5418 if (r == null) {
5419 throw new SecurityException(
5420 "Unable to find app for caller " + caller
5421 + " (pid=" + Binder.getCallingPid()
5422 + ") when getting content provider " + name);
5423 }
5424 }
5425
5426 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005427 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005428 if (cpr != null) {
5429 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005430 String msg;
5431 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5432 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005433 }
5434
5435 if (r != null && cpr.canRunHere(r)) {
5436 // This provider has been published or is in the process
5437 // of being published... but it is also allowed to run
5438 // in the caller's process, so don't make a connection
5439 // and just let the caller instantiate its own instance.
5440 if (cpr.provider != null) {
5441 // don't give caller the provider object, it needs
5442 // to make its own.
5443 cpr = new ContentProviderRecord(cpr);
5444 }
5445 return cpr;
5446 }
5447
5448 final long origId = Binder.clearCallingIdentity();
5449
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005450 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 // return it right away.
5452 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005453 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005454 "Adding provider requested by "
5455 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005456 + cpr.info.processName);
5457 Integer cnt = r.conProviders.get(cpr);
5458 if (cnt == null) {
5459 r.conProviders.put(cpr, new Integer(1));
5460 } else {
5461 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005463 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005464 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5465 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005466 // make sure to count it as being accessed and thus
5467 // back up on the LRU list. This is good because
5468 // content providers are often expensive to start.
5469 updateLruProcessLocked(cpr.app, false, true);
5470 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005471 } else {
5472 cpr.externals++;
5473 }
5474
5475 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005476 updateOomAdjLocked(cpr.app);
5477 }
5478
5479 Binder.restoreCallingIdentity(origId);
5480
5481 } else {
5482 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005483 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005484 resolveContentProvider(name,
5485 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005486 } catch (RemoteException ex) {
5487 }
5488 if (cpi == null) {
5489 return null;
5490 }
5491
Dianne Hackbornb424b632010-08-18 15:59:05 -07005492 String msg;
5493 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5494 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005495 }
5496
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005497 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005498 && !cpi.processName.equals("system")) {
5499 // If this content provider does not run in the system
5500 // process, and the system is not yet ready to run other
5501 // processes, then fail fast instead of hanging.
5502 throw new IllegalArgumentException(
5503 "Attempt to launch content provider before system ready");
5504 }
5505
Dianne Hackborn860755f2010-06-03 18:47:52 -07005506 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005507 final boolean firstClass = cpr == null;
5508 if (firstClass) {
5509 try {
5510 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005511 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005512 getApplicationInfo(
5513 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005514 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005515 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005516 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005517 + cpi.name);
5518 return null;
5519 }
5520 cpr = new ContentProviderRecord(cpi, ai);
5521 } catch (RemoteException ex) {
5522 // pm is in same process, this will never happen.
5523 }
5524 }
5525
5526 if (r != null && cpr.canRunHere(r)) {
5527 // If this is a multiprocess provider, then just return its
5528 // info and allow the caller to instantiate it. Only do
5529 // this if the provider is the same user as the caller's
5530 // process, or can run as root (so can be in any process).
5531 return cpr;
5532 }
5533
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005534 if (DEBUG_PROVIDER) {
5535 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005536 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005537 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005538 }
5539
5540 // This is single process, and our app is now connecting to it.
5541 // See if we are already in the process of launching this
5542 // provider.
5543 final int N = mLaunchingProviders.size();
5544 int i;
5545 for (i=0; i<N; i++) {
5546 if (mLaunchingProviders.get(i) == cpr) {
5547 break;
5548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005549 }
5550
5551 // If the provider is not already being launched, then get it
5552 // started.
5553 if (i >= N) {
5554 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005555
5556 try {
5557 // Content provider is now in use, its package can't be stopped.
5558 try {
5559 AppGlobals.getPackageManager().setPackageStoppedState(
5560 cpr.appInfo.packageName, false);
5561 } catch (RemoteException e) {
5562 }
5563
5564 ProcessRecord proc = startProcessLocked(cpi.processName,
5565 cpr.appInfo, false, 0, "content provider",
5566 new ComponentName(cpi.applicationInfo.packageName,
5567 cpi.name), false);
5568 if (proc == null) {
5569 Slog.w(TAG, "Unable to launch app "
5570 + cpi.applicationInfo.packageName + "/"
5571 + cpi.applicationInfo.uid + " for provider "
5572 + name + ": process is bad");
5573 return null;
5574 }
5575 cpr.launchingApp = proc;
5576 mLaunchingProviders.add(cpr);
5577 } finally {
5578 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005580 }
5581
5582 // Make sure the provider is published (the same provider class
5583 // may be published under multiple names).
5584 if (firstClass) {
5585 mProvidersByClass.put(cpi.name, cpr);
5586 }
5587 mProvidersByName.put(name, cpr);
5588
5589 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005590 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005591 "Adding provider requested by "
5592 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005593 + cpr.info.processName);
5594 Integer cnt = r.conProviders.get(cpr);
5595 if (cnt == null) {
5596 r.conProviders.put(cpr, new Integer(1));
5597 } else {
5598 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5599 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005600 cpr.clients.add(r);
5601 } else {
5602 cpr.externals++;
5603 }
5604 }
5605 }
5606
5607 // Wait for the provider to be published...
5608 synchronized (cpr) {
5609 while (cpr.provider == null) {
5610 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005611 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005612 + cpi.applicationInfo.packageName + "/"
5613 + cpi.applicationInfo.uid + " for provider "
5614 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005615 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005616 cpi.applicationInfo.packageName,
5617 cpi.applicationInfo.uid, name);
5618 return null;
5619 }
5620 try {
5621 cpr.wait();
5622 } catch (InterruptedException ex) {
5623 }
5624 }
5625 }
5626 return cpr;
5627 }
5628
5629 public final ContentProviderHolder getContentProvider(
5630 IApplicationThread caller, String name) {
5631 if (caller == null) {
5632 String msg = "null IApplicationThread when getting content provider "
5633 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005634 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005635 throw new SecurityException(msg);
5636 }
5637
5638 return getContentProviderImpl(caller, name);
5639 }
5640
5641 private ContentProviderHolder getContentProviderExternal(String name) {
5642 return getContentProviderImpl(null, name);
5643 }
5644
5645 /**
5646 * Drop a content provider from a ProcessRecord's bookkeeping
5647 * @param cpr
5648 */
5649 public void removeContentProvider(IApplicationThread caller, String name) {
5650 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005651 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005652 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005653 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005654 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005655 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005656 return;
5657 }
5658 final ProcessRecord r = getRecordForAppLocked(caller);
5659 if (r == null) {
5660 throw new SecurityException(
5661 "Unable to find app for caller " + caller +
5662 " when removing content provider " + name);
5663 }
5664 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005665 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005666 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005667 + r.info.processName + " from process "
5668 + localCpr.appInfo.processName);
5669 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005670 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005671 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005672 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005673 return;
5674 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005675 Integer cnt = r.conProviders.get(localCpr);
5676 if (cnt == null || cnt.intValue() <= 1) {
5677 localCpr.clients.remove(r);
5678 r.conProviders.remove(localCpr);
5679 } else {
5680 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5681 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 }
5683 updateOomAdjLocked();
5684 }
5685 }
5686
5687 private void removeContentProviderExternal(String name) {
5688 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005689 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005690 if(cpr == null) {
5691 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005692 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005693 return;
5694 }
5695
5696 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005697 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005698 localCpr.externals--;
5699 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005700 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 }
5702 updateOomAdjLocked();
5703 }
5704 }
5705
5706 public final void publishContentProviders(IApplicationThread caller,
5707 List<ContentProviderHolder> providers) {
5708 if (providers == null) {
5709 return;
5710 }
5711
5712 synchronized(this) {
5713 final ProcessRecord r = getRecordForAppLocked(caller);
5714 if (r == null) {
5715 throw new SecurityException(
5716 "Unable to find app for caller " + caller
5717 + " (pid=" + Binder.getCallingPid()
5718 + ") when publishing content providers");
5719 }
5720
5721 final long origId = Binder.clearCallingIdentity();
5722
5723 final int N = providers.size();
5724 for (int i=0; i<N; i++) {
5725 ContentProviderHolder src = providers.get(i);
5726 if (src == null || src.info == null || src.provider == null) {
5727 continue;
5728 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005729 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 if (dst != null) {
5731 mProvidersByClass.put(dst.info.name, dst);
5732 String names[] = dst.info.authority.split(";");
5733 for (int j = 0; j < names.length; j++) {
5734 mProvidersByName.put(names[j], dst);
5735 }
5736
5737 int NL = mLaunchingProviders.size();
5738 int j;
5739 for (j=0; j<NL; j++) {
5740 if (mLaunchingProviders.get(j) == dst) {
5741 mLaunchingProviders.remove(j);
5742 j--;
5743 NL--;
5744 }
5745 }
5746 synchronized (dst) {
5747 dst.provider = src.provider;
5748 dst.app = r;
5749 dst.notifyAll();
5750 }
5751 updateOomAdjLocked(r);
5752 }
5753 }
5754
5755 Binder.restoreCallingIdentity(origId);
5756 }
5757 }
5758
5759 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005760 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005761 synchronized (mSelf) {
5762 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5763 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005764 if (providers != null) {
5765 for (int i=providers.size()-1; i>=0; i--) {
5766 ProviderInfo pi = (ProviderInfo)providers.get(i);
5767 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5768 Slog.w(TAG, "Not installing system proc provider " + pi.name
5769 + ": not system .apk");
5770 providers.remove(i);
5771 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005772 }
5773 }
5774 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005775 if (providers != null) {
5776 mSystemThread.installSystemProviders(providers);
5777 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005778
5779 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005780 }
5781
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005782 /**
5783 * Allows app to retrieve the MIME type of a URI without having permission
5784 * to access its content provider.
5785 *
5786 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5787 *
5788 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5789 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5790 */
5791 public String getProviderMimeType(Uri uri) {
5792 final String name = uri.getAuthority();
5793 final long ident = Binder.clearCallingIdentity();
5794 ContentProviderHolder holder = null;
5795
5796 try {
5797 holder = getContentProviderExternal(name);
5798 if (holder != null) {
5799 return holder.provider.getType(uri);
5800 }
5801 } catch (RemoteException e) {
5802 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5803 return null;
5804 } finally {
5805 if (holder != null) {
5806 removeContentProviderExternal(name);
5807 }
5808 Binder.restoreCallingIdentity(ident);
5809 }
5810
5811 return null;
5812 }
5813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005814 // =========================================================
5815 // GLOBAL MANAGEMENT
5816 // =========================================================
5817
5818 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5819 ApplicationInfo info, String customProcess) {
5820 String proc = customProcess != null ? customProcess : info.processName;
5821 BatteryStatsImpl.Uid.Proc ps = null;
5822 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5823 synchronized (stats) {
5824 ps = stats.getProcessStatsLocked(info.uid, proc);
5825 }
5826 return new ProcessRecord(ps, thread, info, proc);
5827 }
5828
5829 final ProcessRecord addAppLocked(ApplicationInfo info) {
5830 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5831
5832 if (app == null) {
5833 app = newProcessRecordLocked(null, info, null);
5834 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005835 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005836 }
5837
Dianne Hackborne7f97212011-02-24 14:40:20 -08005838 // This package really, really can not be stopped.
5839 try {
5840 AppGlobals.getPackageManager().setPackageStoppedState(
5841 info.packageName, false);
5842 } catch (RemoteException e) {
5843 }
5844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005845 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5846 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5847 app.persistent = true;
5848 app.maxAdj = CORE_SERVER_ADJ;
5849 }
5850 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5851 mPersistentStartingProcesses.add(app);
5852 startProcessLocked(app, "added application", app.processName);
5853 }
5854
5855 return app;
5856 }
5857
5858 public void unhandledBack() {
5859 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5860 "unhandledBack()");
5861
5862 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005863 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005864 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865 TAG, "Performing unhandledBack(): stack size = " + count);
5866 if (count > 1) {
5867 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005868 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005869 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5870 Binder.restoreCallingIdentity(origId);
5871 }
5872 }
5873 }
5874
5875 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5876 String name = uri.getAuthority();
5877 ContentProviderHolder cph = getContentProviderExternal(name);
5878 ParcelFileDescriptor pfd = null;
5879 if (cph != null) {
5880 // We record the binder invoker's uid in thread-local storage before
5881 // going to the content provider to open the file. Later, in the code
5882 // that handles all permissions checks, we look for this uid and use
5883 // that rather than the Activity Manager's own uid. The effect is that
5884 // we do the check against the caller's permissions even though it looks
5885 // to the content provider like the Activity Manager itself is making
5886 // the request.
5887 sCallerIdentity.set(new Identity(
5888 Binder.getCallingPid(), Binder.getCallingUid()));
5889 try {
5890 pfd = cph.provider.openFile(uri, "r");
5891 } catch (FileNotFoundException e) {
5892 // do nothing; pfd will be returned null
5893 } finally {
5894 // Ensure that whatever happens, we clean up the identity state
5895 sCallerIdentity.remove();
5896 }
5897
5898 // We've got the fd now, so we're done with the provider.
5899 removeContentProviderExternal(name);
5900 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005901 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005902 }
5903 return pfd;
5904 }
5905
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005906 // Actually is sleeping or shutting down or whatever else in the future
5907 // is an inactive state.
5908 public boolean isSleeping() {
5909 return mSleeping || mShuttingDown;
5910 }
5911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005912 public void goingToSleep() {
5913 synchronized(this) {
5914 mSleeping = true;
5915 mWindowManager.setEventDispatching(false);
5916
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005917 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005918
5919 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005920 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005921 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5922 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005923 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005924 }
5925 }
5926
Dianne Hackborn55280a92009-05-07 15:53:46 -07005927 public boolean shutdown(int timeout) {
5928 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5929 != PackageManager.PERMISSION_GRANTED) {
5930 throw new SecurityException("Requires permission "
5931 + android.Manifest.permission.SHUTDOWN);
5932 }
5933
5934 boolean timedout = false;
5935
5936 synchronized(this) {
5937 mShuttingDown = true;
5938 mWindowManager.setEventDispatching(false);
5939
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005940 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005941 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005942 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005943 while (mMainStack.mResumedActivity != null
5944 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005945 long delay = endTime - System.currentTimeMillis();
5946 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005947 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005948 timedout = true;
5949 break;
5950 }
5951 try {
5952 this.wait();
5953 } catch (InterruptedException e) {
5954 }
5955 }
5956 }
5957 }
5958
5959 mUsageStatsService.shutdown();
5960 mBatteryStatsService.shutdown();
5961
5962 return timedout;
5963 }
5964
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005965 public final void activitySlept(IBinder token) {
5966 if (localLOGV) Slog.v(
5967 TAG, "Activity slept: token=" + token);
5968
5969 ActivityRecord r = null;
5970
5971 final long origId = Binder.clearCallingIdentity();
5972
5973 synchronized (this) {
5974 int index = mMainStack.indexOfTokenLocked(token);
5975 if (index >= 0) {
5976 r = (ActivityRecord)mMainStack.mHistory.get(index);
5977 mMainStack.activitySleptLocked(r);
5978 }
5979 }
5980
5981 Binder.restoreCallingIdentity(origId);
5982 }
5983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 public void wakingUp() {
5985 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005986 mWindowManager.setEventDispatching(true);
5987 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005988 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005989 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005990 }
5991 }
5992
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005993 public void stopAppSwitches() {
5994 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5995 != PackageManager.PERMISSION_GRANTED) {
5996 throw new SecurityException("Requires permission "
5997 + android.Manifest.permission.STOP_APP_SWITCHES);
5998 }
5999
6000 synchronized(this) {
6001 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6002 + APP_SWITCH_DELAY_TIME;
6003 mDidAppSwitch = false;
6004 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6005 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6006 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6007 }
6008 }
6009
6010 public void resumeAppSwitches() {
6011 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6012 != PackageManager.PERMISSION_GRANTED) {
6013 throw new SecurityException("Requires permission "
6014 + android.Manifest.permission.STOP_APP_SWITCHES);
6015 }
6016
6017 synchronized(this) {
6018 // Note that we don't execute any pending app switches... we will
6019 // let those wait until either the timeout, or the next start
6020 // activity request.
6021 mAppSwitchesAllowedTime = 0;
6022 }
6023 }
6024
6025 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6026 String name) {
6027 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6028 return true;
6029 }
6030
6031 final int perm = checkComponentPermission(
6032 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006033 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006034 if (perm == PackageManager.PERMISSION_GRANTED) {
6035 return true;
6036 }
6037
Joe Onorato8a9b2202010-02-26 18:56:32 -08006038 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006039 return false;
6040 }
6041
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 public void setDebugApp(String packageName, boolean waitForDebugger,
6043 boolean persistent) {
6044 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6045 "setDebugApp()");
6046
6047 // Note that this is not really thread safe if there are multiple
6048 // callers into it at the same time, but that's not a situation we
6049 // care about.
6050 if (persistent) {
6051 final ContentResolver resolver = mContext.getContentResolver();
6052 Settings.System.putString(
6053 resolver, Settings.System.DEBUG_APP,
6054 packageName);
6055 Settings.System.putInt(
6056 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6057 waitForDebugger ? 1 : 0);
6058 }
6059
6060 synchronized (this) {
6061 if (!persistent) {
6062 mOrigDebugApp = mDebugApp;
6063 mOrigWaitForDebugger = mWaitForDebugger;
6064 }
6065 mDebugApp = packageName;
6066 mWaitForDebugger = waitForDebugger;
6067 mDebugTransient = !persistent;
6068 if (packageName != null) {
6069 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006070 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006071 Binder.restoreCallingIdentity(origId);
6072 }
6073 }
6074 }
6075
6076 public void setAlwaysFinish(boolean enabled) {
6077 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6078 "setAlwaysFinish()");
6079
6080 Settings.System.putInt(
6081 mContext.getContentResolver(),
6082 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6083
6084 synchronized (this) {
6085 mAlwaysFinishActivities = enabled;
6086 }
6087 }
6088
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006089 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006090 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006091 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006092 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006093 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006094 }
6095 }
6096
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006097 public boolean isUserAMonkey() {
6098 // For now the fact that there is a controller implies
6099 // we have a monkey.
6100 synchronized (this) {
6101 return mController != null;
6102 }
6103 }
6104
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006105 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006106 synchronized (this) {
6107 mWatchers.register(watcher);
6108 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006109 }
6110
6111 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006112 synchronized (this) {
6113 mWatchers.unregister(watcher);
6114 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006115 }
6116
Daniel Sandler69a48172010-06-23 16:29:36 -04006117 public void setImmersive(IBinder token, boolean immersive) {
6118 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006119 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006120 if (index < 0) {
6121 throw new IllegalArgumentException();
6122 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006123 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006124 r.immersive = immersive;
6125 }
6126 }
6127
6128 public boolean isImmersive(IBinder token) {
6129 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006130 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006131 if (index < 0) {
6132 throw new IllegalArgumentException();
6133 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006134 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006135 return r.immersive;
6136 }
6137 }
6138
6139 public boolean isTopActivityImmersive() {
6140 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006141 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006142 return (r != null) ? r.immersive : false;
6143 }
6144 }
6145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006146 public final void enterSafeMode() {
6147 synchronized(this) {
6148 // It only makes sense to do this before the system is ready
6149 // and started launching other packages.
6150 if (!mSystemReady) {
6151 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006152 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006153 } catch (RemoteException e) {
6154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006155 }
6156 }
6157 }
6158
Jeff Brownb09abc12011-01-13 21:08:27 -08006159 public final void showSafeModeOverlay() {
6160 View v = LayoutInflater.from(mContext).inflate(
6161 com.android.internal.R.layout.safe_mode, null);
6162 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6163 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6164 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6165 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6166 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6167 lp.format = v.getBackground().getOpacity();
6168 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6169 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6170 ((WindowManager)mContext.getSystemService(
6171 Context.WINDOW_SERVICE)).addView(v, lp);
6172 }
6173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006174 public void noteWakeupAlarm(IIntentSender sender) {
6175 if (!(sender instanceof PendingIntentRecord)) {
6176 return;
6177 }
6178 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6179 synchronized (stats) {
6180 if (mBatteryStatsService.isOnBattery()) {
6181 mBatteryStatsService.enforceCallingPermission();
6182 PendingIntentRecord rec = (PendingIntentRecord)sender;
6183 int MY_UID = Binder.getCallingUid();
6184 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6185 BatteryStatsImpl.Uid.Pkg pkg =
6186 stats.getPackageStatsLocked(uid, rec.key.packageName);
6187 pkg.incWakeupsLocked();
6188 }
6189 }
6190 }
6191
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006192 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006193 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006194 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006195 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006196 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006197 // XXX Note: don't acquire main activity lock here, because the window
6198 // manager calls in with its locks held.
6199
6200 boolean killed = false;
6201 synchronized (mPidsSelfLocked) {
6202 int[] types = new int[pids.length];
6203 int worstType = 0;
6204 for (int i=0; i<pids.length; i++) {
6205 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6206 if (proc != null) {
6207 int type = proc.setAdj;
6208 types[i] = type;
6209 if (type > worstType) {
6210 worstType = type;
6211 }
6212 }
6213 }
6214
6215 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6216 // then constrain it so we will kill all hidden procs.
6217 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6218 worstType = HIDDEN_APP_MIN_ADJ;
6219 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006220 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006221 for (int i=0; i<pids.length; i++) {
6222 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6223 if (proc == null) {
6224 continue;
6225 }
6226 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006227 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006228 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006229 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6230 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006231 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006232 proc.killedBackground = true;
6233 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006234 }
6235 }
6236 }
6237 return killed;
6238 }
6239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006240 public final void startRunning(String pkg, String cls, String action,
6241 String data) {
6242 synchronized(this) {
6243 if (mStartRunning) {
6244 return;
6245 }
6246 mStartRunning = true;
6247 mTopComponent = pkg != null && cls != null
6248 ? new ComponentName(pkg, cls) : null;
6249 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6250 mTopData = data;
6251 if (!mSystemReady) {
6252 return;
6253 }
6254 }
6255
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006256 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006257 }
6258
6259 private void retrieveSettings() {
6260 final ContentResolver resolver = mContext.getContentResolver();
6261 String debugApp = Settings.System.getString(
6262 resolver, Settings.System.DEBUG_APP);
6263 boolean waitForDebugger = Settings.System.getInt(
6264 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6265 boolean alwaysFinishActivities = Settings.System.getInt(
6266 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6267
6268 Configuration configuration = new Configuration();
6269 Settings.System.getConfiguration(resolver, configuration);
6270
6271 synchronized (this) {
6272 mDebugApp = mOrigDebugApp = debugApp;
6273 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6274 mAlwaysFinishActivities = alwaysFinishActivities;
6275 // This happens before any activities are started, so we can
6276 // change mConfiguration in-place.
6277 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006278 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006279 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006280 }
6281 }
6282
6283 public boolean testIsSystemReady() {
6284 // no need to synchronize(this) just to read & return the value
6285 return mSystemReady;
6286 }
6287
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006288 private static File getCalledPreBootReceiversFile() {
6289 File dataDir = Environment.getDataDirectory();
6290 File systemDir = new File(dataDir, "system");
6291 File fname = new File(systemDir, "called_pre_boots.dat");
6292 return fname;
6293 }
6294
6295 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6296 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6297 File file = getCalledPreBootReceiversFile();
6298 FileInputStream fis = null;
6299 try {
6300 fis = new FileInputStream(file);
6301 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6302 int vers = dis.readInt();
6303 String codename = dis.readUTF();
6304 if (vers == android.os.Build.VERSION.SDK_INT
6305 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6306 int num = dis.readInt();
6307 while (num > 0) {
6308 num--;
6309 String pkg = dis.readUTF();
6310 String cls = dis.readUTF();
6311 lastDoneReceivers.add(new ComponentName(pkg, cls));
6312 }
6313 }
6314 } catch (FileNotFoundException e) {
6315 } catch (IOException e) {
6316 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6317 } finally {
6318 if (fis != null) {
6319 try {
6320 fis.close();
6321 } catch (IOException e) {
6322 }
6323 }
6324 }
6325 return lastDoneReceivers;
6326 }
6327
6328 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6329 File file = getCalledPreBootReceiversFile();
6330 FileOutputStream fos = null;
6331 DataOutputStream dos = null;
6332 try {
6333 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6334 fos = new FileOutputStream(file);
6335 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6336 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6337 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6338 dos.writeInt(list.size());
6339 for (int i=0; i<list.size(); i++) {
6340 dos.writeUTF(list.get(i).getPackageName());
6341 dos.writeUTF(list.get(i).getClassName());
6342 }
6343 } catch (IOException e) {
6344 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6345 file.delete();
6346 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006347 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006348 if (dos != null) {
6349 try {
6350 dos.close();
6351 } catch (IOException e) {
6352 // TODO Auto-generated catch block
6353 e.printStackTrace();
6354 }
6355 }
6356 }
6357 }
6358
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006359 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006360 // In the simulator, startRunning will never have been called, which
6361 // normally sets a few crucial variables. Do it here instead.
6362 if (!Process.supportsProcesses()) {
6363 mStartRunning = true;
6364 mTopAction = Intent.ACTION_MAIN;
6365 }
6366
6367 synchronized(this) {
6368 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006369 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006370 return;
6371 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006372
6373 // Check to see if there are any update receivers to run.
6374 if (!mDidUpdate) {
6375 if (mWaitingUpdate) {
6376 return;
6377 }
6378 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6379 List<ResolveInfo> ris = null;
6380 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006381 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006382 intent, null, 0);
6383 } catch (RemoteException e) {
6384 }
6385 if (ris != null) {
6386 for (int i=ris.size()-1; i>=0; i--) {
6387 if ((ris.get(i).activityInfo.applicationInfo.flags
6388 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6389 ris.remove(i);
6390 }
6391 }
6392 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006393
6394 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6395
6396 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006397 for (int i=0; i<ris.size(); i++) {
6398 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006399 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6400 if (lastDoneReceivers.contains(comp)) {
6401 ris.remove(i);
6402 i--;
6403 }
6404 }
6405
6406 for (int i=0; i<ris.size(); i++) {
6407 ActivityInfo ai = ris.get(i).activityInfo;
6408 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6409 doneReceivers.add(comp);
6410 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006411 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006412 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006413 finisher = new IIntentReceiver.Stub() {
6414 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006415 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006416 boolean sticky) {
6417 // The raw IIntentReceiver interface is called
6418 // with the AM lock held, so redispatch to
6419 // execute our code without the lock.
6420 mHandler.post(new Runnable() {
6421 public void run() {
6422 synchronized (ActivityManagerService.this) {
6423 mDidUpdate = true;
6424 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006425 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006426 systemReady(goingCallback);
6427 }
6428 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006429 }
6430 };
6431 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006432 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006433 broadcastIntentLocked(null, null, intent, null, finisher,
6434 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006435 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006436 mWaitingUpdate = true;
6437 }
6438 }
6439 }
6440 if (mWaitingUpdate) {
6441 return;
6442 }
6443 mDidUpdate = true;
6444 }
6445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006446 mSystemReady = true;
6447 if (!mStartRunning) {
6448 return;
6449 }
6450 }
6451
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006452 ArrayList<ProcessRecord> procsToKill = null;
6453 synchronized(mPidsSelfLocked) {
6454 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6455 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6456 if (!isAllowedWhileBooting(proc.info)){
6457 if (procsToKill == null) {
6458 procsToKill = new ArrayList<ProcessRecord>();
6459 }
6460 procsToKill.add(proc);
6461 }
6462 }
6463 }
6464
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006465 synchronized(this) {
6466 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006467 for (int i=procsToKill.size()-1; i>=0; i--) {
6468 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006469 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006470 removeProcessLocked(proc, true);
6471 }
6472 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006473
6474 // Now that we have cleaned up any update processes, we
6475 // are ready to start launching real processes and know that
6476 // we won't trample on them any more.
6477 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006478 }
6479
Joe Onorato8a9b2202010-02-26 18:56:32 -08006480 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006481 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006482 SystemClock.uptimeMillis());
6483
6484 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006485 // Make sure we have no pre-ready processes sitting around.
6486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006487 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6488 ResolveInfo ri = mContext.getPackageManager()
6489 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006490 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006491 CharSequence errorMsg = null;
6492 if (ri != null) {
6493 ActivityInfo ai = ri.activityInfo;
6494 ApplicationInfo app = ai.applicationInfo;
6495 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6496 mTopAction = Intent.ACTION_FACTORY_TEST;
6497 mTopData = null;
6498 mTopComponent = new ComponentName(app.packageName,
6499 ai.name);
6500 } else {
6501 errorMsg = mContext.getResources().getText(
6502 com.android.internal.R.string.factorytest_not_system);
6503 }
6504 } else {
6505 errorMsg = mContext.getResources().getText(
6506 com.android.internal.R.string.factorytest_no_action);
6507 }
6508 if (errorMsg != null) {
6509 mTopAction = null;
6510 mTopData = null;
6511 mTopComponent = null;
6512 Message msg = Message.obtain();
6513 msg.what = SHOW_FACTORY_ERROR_MSG;
6514 msg.getData().putCharSequence("msg", errorMsg);
6515 mHandler.sendMessage(msg);
6516 }
6517 }
6518 }
6519
6520 retrieveSettings();
6521
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006522 if (goingCallback != null) goingCallback.run();
6523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006524 synchronized (this) {
6525 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6526 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006527 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006528 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006529 if (apps != null) {
6530 int N = apps.size();
6531 int i;
6532 for (i=0; i<N; i++) {
6533 ApplicationInfo info
6534 = (ApplicationInfo)apps.get(i);
6535 if (info != null &&
6536 !info.packageName.equals("android")) {
6537 addAppLocked(info);
6538 }
6539 }
6540 }
6541 } catch (RemoteException ex) {
6542 // pm is in same process, this will never happen.
6543 }
6544 }
6545
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006546 // Start up initial activity.
6547 mBooting = true;
6548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006549 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006550 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006551 Message msg = Message.obtain();
6552 msg.what = SHOW_UID_ERROR_MSG;
6553 mHandler.sendMessage(msg);
6554 }
6555 } catch (RemoteException e) {
6556 }
6557
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006558 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006559 }
6560 }
6561
Dan Egnorb7f03672009-12-09 16:22:32 -08006562 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006563 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006565 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006566 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006567 startAppProblemLocked(app);
6568 app.stopFreezingAllLocked();
6569 return handleAppCrashLocked(app);
6570 }
6571
Dan Egnorb7f03672009-12-09 16:22:32 -08006572 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006573 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006574 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006575 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006576 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6577 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006578 startAppProblemLocked(app);
6579 app.stopFreezingAllLocked();
6580 }
6581
6582 /**
6583 * Generate a process error record, suitable for attachment to a ProcessRecord.
6584 *
6585 * @param app The ProcessRecord in which the error occurred.
6586 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6587 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006588 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006589 * @param shortMsg Short message describing the crash.
6590 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006591 * @param stackTrace Full crash stack trace, may be null.
6592 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006593 * @return Returns a fully-formed AppErrorStateInfo record.
6594 */
6595 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006596 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006597 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006599 report.condition = condition;
6600 report.processName = app.processName;
6601 report.pid = app.pid;
6602 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006603 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006604 report.shortMsg = shortMsg;
6605 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006606 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006607
6608 return report;
6609 }
6610
Dan Egnor42471dd2010-01-07 17:25:22 -08006611 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006612 synchronized (this) {
6613 app.crashing = false;
6614 app.crashingReport = null;
6615 app.notResponding = false;
6616 app.notRespondingReport = null;
6617 if (app.anrDialog == fromDialog) {
6618 app.anrDialog = null;
6619 }
6620 if (app.waitDialog == fromDialog) {
6621 app.waitDialog = null;
6622 }
6623 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006624 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006625 Slog.i(ActivityManagerService.TAG, "Killing "
6626 + app.processName + " (pid=" + app.pid + "): user's request");
6627 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6628 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006629 Process.killProcess(app.pid);
6630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006631 }
6632 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006633
Dan Egnorb7f03672009-12-09 16:22:32 -08006634 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006635 long now = SystemClock.uptimeMillis();
6636
6637 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6638 app.info.uid);
6639 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6640 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006641 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006642 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006643 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006644 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006645 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6646 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006647 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006648 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006649 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006650 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006651 }
6652 }
6653 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006654 // Don't let services in this process be restarted and potentially
6655 // annoy the user repeatedly. Unless it is persistent, since those
6656 // processes run critical code.
6657 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 // We don't want to start this process again until the user
6659 // explicitly does so... but for persistent process, we really
6660 // need to keep it running. If a persistent process is actually
6661 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006662 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006663 app.info.processName);
6664 mBadProcesses.put(app.info.processName, app.info.uid, now);
6665 app.bad = true;
6666 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6667 app.removed = true;
6668 removeProcessLocked(app, false);
6669 return false;
6670 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006671 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006672 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006673 if (r.app == app) {
6674 // If the top running activity is from this crashing
6675 // process, then terminate it to avoid getting in a loop.
6676 Slog.w(TAG, " Force finishing activity "
6677 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006678 int index = mMainStack.indexOfTokenLocked(r);
6679 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006680 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006681 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006682 // stopped, to avoid a situation where one will get
6683 // re-start our crashing activity once it gets resumed again.
6684 index--;
6685 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006686 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006687 if (r.state == ActivityState.RESUMED
6688 || r.state == ActivityState.PAUSING
6689 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006690 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006691 Slog.w(TAG, " Force finishing activity "
6692 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006693 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006694 Activity.RESULT_CANCELED, null, "crashed");
6695 }
6696 }
6697 }
6698 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699 }
6700
6701 // Bump up the crash count of any services currently running in the proc.
6702 if (app.services.size() != 0) {
6703 // Any services running in the application need to be placed
6704 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006705 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006706 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006707 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006708 sr.crashCount++;
6709 }
6710 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006711
6712 // If the crashing process is what we consider to be the "home process" and it has been
6713 // replaced by a third-party app, clear the package preferred activities from packages
6714 // with a home activity running in the process to prevent a repeatedly crashing app
6715 // from blocking the user to manually clear the list.
6716 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6717 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6718 Iterator it = mHomeProcess.activities.iterator();
6719 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006720 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006721 if (r.isHomeActivity) {
6722 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6723 try {
6724 ActivityThread.getPackageManager()
6725 .clearPackagePreferredActivities(r.packageName);
6726 } catch (RemoteException c) {
6727 // pm is in same process, this will never happen.
6728 }
6729 }
6730 }
6731 }
6732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006733 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6734 return true;
6735 }
6736
6737 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006738 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6739 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006740 skipCurrentReceiverLocked(app);
6741 }
6742
6743 void skipCurrentReceiverLocked(ProcessRecord app) {
6744 boolean reschedule = false;
6745 BroadcastRecord r = app.curReceiver;
6746 if (r != null) {
6747 // The current broadcast is waiting for this app's receiver
6748 // to be finished. Looks like that's not going to happen, so
6749 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006750 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006751 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6752 r.resultExtras, r.resultAbort, true);
6753 reschedule = true;
6754 }
6755 r = mPendingBroadcast;
6756 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006757 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006758 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006759 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006760 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6761 r.resultExtras, r.resultAbort, true);
6762 reschedule = true;
6763 }
6764 if (reschedule) {
6765 scheduleBroadcastsLocked();
6766 }
6767 }
6768
Dan Egnor60d87622009-12-16 16:32:58 -08006769 /**
6770 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6771 * The application process will exit immediately after this call returns.
6772 * @param app object of the crashing app, null for the system server
6773 * @param crashInfo describing the exception
6774 */
6775 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6776 ProcessRecord r = findAppProcess(app);
6777
6778 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6779 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006780 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006781 crashInfo.exceptionClassName,
6782 crashInfo.exceptionMessage,
6783 crashInfo.throwFileName,
6784 crashInfo.throwLineNumber);
6785
Dan Egnor42471dd2010-01-07 17:25:22 -08006786 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006787
6788 crashApplication(r, crashInfo);
6789 }
6790
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006791 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006792 IBinder app,
6793 int violationMask,
6794 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006795 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006796
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006797 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006798 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006799 boolean logIt = true;
6800 synchronized (mAlreadyLoggedViolatedStacks) {
6801 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6802 logIt = false;
6803 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006804 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006805 // the relative pain numbers, without logging all
6806 // the stack traces repeatedly. We'd want to do
6807 // likewise in the client code, which also does
6808 // dup suppression, before the Binder call.
6809 } else {
6810 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6811 mAlreadyLoggedViolatedStacks.clear();
6812 }
6813 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6814 }
6815 }
6816 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006817 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006818 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006819 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006820
6821 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6822 AppErrorResult result = new AppErrorResult();
6823 synchronized (this) {
6824 final long origId = Binder.clearCallingIdentity();
6825
6826 Message msg = Message.obtain();
6827 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6828 HashMap<String, Object> data = new HashMap<String, Object>();
6829 data.put("result", result);
6830 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006831 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006832 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006833 msg.obj = data;
6834 mHandler.sendMessage(msg);
6835
6836 Binder.restoreCallingIdentity(origId);
6837 }
6838 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006839 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006840 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006841 }
6842
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006843 // Depending on the policy in effect, there could be a bunch of
6844 // these in quick succession so we try to batch these together to
6845 // minimize disk writes, number of dropbox entries, and maximize
6846 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006847 private void logStrictModeViolationToDropBox(
6848 ProcessRecord process,
6849 StrictMode.ViolationInfo info) {
6850 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006851 return;
6852 }
6853 final boolean isSystemApp = process == null ||
6854 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6855 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6856 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6857 final DropBoxManager dbox = (DropBoxManager)
6858 mContext.getSystemService(Context.DROPBOX_SERVICE);
6859
6860 // Exit early if the dropbox isn't configured to accept this report type.
6861 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6862
6863 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006864 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006865 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6866 synchronized (sb) {
6867 bufferWasEmpty = sb.length() == 0;
6868 appendDropBoxProcessHeaders(process, sb);
6869 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6870 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006871 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6872 if (info.violationNumThisLoop != 0) {
6873 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6874 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006875 if (info.numAnimationsRunning != 0) {
6876 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6877 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006878 if (info.broadcastIntentAction != null) {
6879 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6880 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006881 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006882 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006883 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08006884 if (info.numInstances != -1) {
6885 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
6886 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006887 if (info.tags != null) {
6888 for (String tag : info.tags) {
6889 sb.append("Span-Tag: ").append(tag).append("\n");
6890 }
6891 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006892 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006893 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6894 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006895 }
6896 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006897
6898 // Only buffer up to ~64k. Various logging bits truncate
6899 // things at 128k.
6900 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006901 }
6902
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006903 // Flush immediately if the buffer's grown too large, or this
6904 // is a non-system app. Non-system apps are isolated with a
6905 // different tag & policy and not batched.
6906 //
6907 // Batching is useful during internal testing with
6908 // StrictMode settings turned up high. Without batching,
6909 // thousands of separate files could be created on boot.
6910 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006911 new Thread("Error dump: " + dropboxTag) {
6912 @Override
6913 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006914 String report;
6915 synchronized (sb) {
6916 report = sb.toString();
6917 sb.delete(0, sb.length());
6918 sb.trimToSize();
6919 }
6920 if (report.length() != 0) {
6921 dbox.addText(dropboxTag, report);
6922 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006923 }
6924 }.start();
6925 return;
6926 }
6927
6928 // System app batching:
6929 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006930 // An existing dropbox-writing thread is outstanding, so
6931 // we don't need to start it up. The existing thread will
6932 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006933 return;
6934 }
6935
6936 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6937 // (After this point, we shouldn't access AMS internal data structures.)
6938 new Thread("Error dump: " + dropboxTag) {
6939 @Override
6940 public void run() {
6941 // 5 second sleep to let stacks arrive and be batched together
6942 try {
6943 Thread.sleep(5000); // 5 seconds
6944 } catch (InterruptedException e) {}
6945
6946 String errorReport;
6947 synchronized (mStrictModeBuffer) {
6948 errorReport = mStrictModeBuffer.toString();
6949 if (errorReport.length() == 0) {
6950 return;
6951 }
6952 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6953 mStrictModeBuffer.trimToSize();
6954 }
6955 dbox.addText(dropboxTag, errorReport);
6956 }
6957 }.start();
6958 }
6959
Dan Egnor60d87622009-12-16 16:32:58 -08006960 /**
6961 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6962 * @param app object of the crashing app, null for the system server
6963 * @param tag reported by the caller
6964 * @param crashInfo describing the context of the error
6965 * @return true if the process should exit immediately (WTF is fatal)
6966 */
6967 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006968 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006969 ProcessRecord r = findAppProcess(app);
6970
6971 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6972 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006973 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006974 tag, crashInfo.exceptionMessage);
6975
Dan Egnor42471dd2010-01-07 17:25:22 -08006976 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006977
Doug Zongker43866e02010-01-07 12:09:54 -08006978 if (Settings.Secure.getInt(mContext.getContentResolver(),
6979 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006980 crashApplication(r, crashInfo);
6981 return true;
6982 } else {
6983 return false;
6984 }
6985 }
6986
6987 /**
6988 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6989 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6990 */
6991 private ProcessRecord findAppProcess(IBinder app) {
6992 if (app == null) {
6993 return null;
6994 }
6995
6996 synchronized (this) {
6997 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6998 final int NA = apps.size();
6999 for (int ia=0; ia<NA; ia++) {
7000 ProcessRecord p = apps.valueAt(ia);
7001 if (p.thread != null && p.thread.asBinder() == app) {
7002 return p;
7003 }
7004 }
7005 }
7006
Joe Onorato8a9b2202010-02-26 18:56:32 -08007007 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007008 return null;
7009 }
7010 }
7011
7012 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007013 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7014 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007015 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007016 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
7017 // Note: ProcessRecord 'process' is guarded by the service
7018 // instance. (notably process.pkgList, which could otherwise change
7019 // concurrently during execution of this method)
7020 synchronized (this) {
7021 if (process == null || process.pid == MY_PID) {
7022 sb.append("Process: system_server\n");
7023 } else {
7024 sb.append("Process: ").append(process.processName).append("\n");
7025 }
7026 if (process == null) {
7027 return;
7028 }
Dan Egnora455d192010-03-12 08:52:28 -08007029 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007030 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007031 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7032 for (String pkg : process.pkgList) {
7033 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007034 try {
Dan Egnora455d192010-03-12 08:52:28 -08007035 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7036 if (pi != null) {
7037 sb.append(" v").append(pi.versionCode);
7038 if (pi.versionName != null) {
7039 sb.append(" (").append(pi.versionName).append(")");
7040 }
7041 }
7042 } catch (RemoteException e) {
7043 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007044 }
Dan Egnora455d192010-03-12 08:52:28 -08007045 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007046 }
Dan Egnora455d192010-03-12 08:52:28 -08007047 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007048 }
7049
7050 private static String processClass(ProcessRecord process) {
7051 if (process == null || process.pid == MY_PID) {
7052 return "system_server";
7053 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7054 return "system_app";
7055 } else {
7056 return "data_app";
7057 }
7058 }
7059
7060 /**
7061 * Write a description of an error (crash, WTF, ANR) to the drop box.
7062 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7063 * @param process which caused the error, null means the system server
7064 * @param activity which triggered the error, null if unknown
7065 * @param parent activity related to the error, null if unknown
7066 * @param subject line related to the error, null if absent
7067 * @param report in long form describing the error, null if absent
7068 * @param logFile to include in the report, null if none
7069 * @param crashInfo giving an application stack trace, null if absent
7070 */
7071 public void addErrorToDropBox(String eventType,
7072 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7073 final String report, final File logFile,
7074 final ApplicationErrorReport.CrashInfo crashInfo) {
7075 // NOTE -- this must never acquire the ActivityManagerService lock,
7076 // otherwise the watchdog may be prevented from resetting the system.
7077
7078 final String dropboxTag = processClass(process) + "_" + eventType;
7079 final DropBoxManager dbox = (DropBoxManager)
7080 mContext.getSystemService(Context.DROPBOX_SERVICE);
7081
7082 // Exit early if the dropbox isn't configured to accept this report type.
7083 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7084
7085 final StringBuilder sb = new StringBuilder(1024);
7086 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007087 if (activity != null) {
7088 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7089 }
7090 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7091 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7092 }
7093 if (parent != null && parent != activity) {
7094 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7095 }
7096 if (subject != null) {
7097 sb.append("Subject: ").append(subject).append("\n");
7098 }
7099 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007100 if (Debug.isDebuggerConnected()) {
7101 sb.append("Debugger: Connected\n");
7102 }
Dan Egnora455d192010-03-12 08:52:28 -08007103 sb.append("\n");
7104
7105 // Do the rest in a worker thread to avoid blocking the caller on I/O
7106 // (After this point, we shouldn't access AMS internal data structures.)
7107 Thread worker = new Thread("Error dump: " + dropboxTag) {
7108 @Override
7109 public void run() {
7110 if (report != null) {
7111 sb.append(report);
7112 }
7113 if (logFile != null) {
7114 try {
7115 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7116 } catch (IOException e) {
7117 Slog.e(TAG, "Error reading " + logFile, e);
7118 }
7119 }
7120 if (crashInfo != null && crashInfo.stackTrace != null) {
7121 sb.append(crashInfo.stackTrace);
7122 }
7123
7124 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7125 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7126 if (lines > 0) {
7127 sb.append("\n");
7128
7129 // Merge several logcat streams, and take the last N lines
7130 InputStreamReader input = null;
7131 try {
7132 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7133 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7134 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7135
7136 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7137 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7138 input = new InputStreamReader(logcat.getInputStream());
7139
7140 int num;
7141 char[] buf = new char[8192];
7142 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7143 } catch (IOException e) {
7144 Slog.e(TAG, "Error running logcat", e);
7145 } finally {
7146 if (input != null) try { input.close(); } catch (IOException e) {}
7147 }
7148 }
7149
7150 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007151 }
Dan Egnora455d192010-03-12 08:52:28 -08007152 };
7153
7154 if (process == null || process.pid == MY_PID) {
7155 worker.run(); // We may be about to die -- need to run this synchronously
7156 } else {
7157 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007158 }
7159 }
7160
7161 /**
7162 * Bring up the "unexpected error" dialog box for a crashing app.
7163 * Deal with edge cases (intercepts from instrumented applications,
7164 * ActivityController, error intent receivers, that sort of thing).
7165 * @param r the application crashing
7166 * @param crashInfo describing the failure
7167 */
7168 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007169 long timeMillis = System.currentTimeMillis();
7170 String shortMsg = crashInfo.exceptionClassName;
7171 String longMsg = crashInfo.exceptionMessage;
7172 String stackTrace = crashInfo.stackTrace;
7173 if (shortMsg != null && longMsg != null) {
7174 longMsg = shortMsg + ": " + longMsg;
7175 } else if (shortMsg != null) {
7176 longMsg = shortMsg;
7177 }
7178
Dan Egnor60d87622009-12-16 16:32:58 -08007179 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007180 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007181 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007182 try {
7183 String name = r != null ? r.processName : null;
7184 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007185 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007186 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007187 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007188 + " at watcher's request");
7189 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007190 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007191 }
7192 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007193 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007194 }
7195 }
7196
7197 final long origId = Binder.clearCallingIdentity();
7198
7199 // If this process is running instrumentation, finish it.
7200 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007201 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007202 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007203 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7204 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007205 Bundle info = new Bundle();
7206 info.putString("shortMsg", shortMsg);
7207 info.putString("longMsg", longMsg);
7208 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7209 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007210 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007211 }
7212
Dan Egnor60d87622009-12-16 16:32:58 -08007213 // If we can't identify the process or it's already exceeded its crash quota,
7214 // quit right away without showing a crash dialog.
7215 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007216 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007217 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007218 }
7219
7220 Message msg = Message.obtain();
7221 msg.what = SHOW_ERROR_MSG;
7222 HashMap data = new HashMap();
7223 data.put("result", result);
7224 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007225 msg.obj = data;
7226 mHandler.sendMessage(msg);
7227
7228 Binder.restoreCallingIdentity(origId);
7229 }
7230
7231 int res = result.get();
7232
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007233 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007234 synchronized (this) {
7235 if (r != null) {
7236 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7237 SystemClock.uptimeMillis());
7238 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007239 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007240 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007241 }
7242 }
7243
7244 if (appErrorIntent != null) {
7245 try {
7246 mContext.startActivity(appErrorIntent);
7247 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007248 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007252
7253 Intent createAppErrorIntentLocked(ProcessRecord r,
7254 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7255 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007256 if (report == null) {
7257 return null;
7258 }
7259 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7260 result.setComponent(r.errorReportReceiver);
7261 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7262 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7263 return result;
7264 }
7265
Dan Egnorb7f03672009-12-09 16:22:32 -08007266 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7267 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007268 if (r.errorReportReceiver == null) {
7269 return null;
7270 }
7271
7272 if (!r.crashing && !r.notResponding) {
7273 return null;
7274 }
7275
Dan Egnorb7f03672009-12-09 16:22:32 -08007276 ApplicationErrorReport report = new ApplicationErrorReport();
7277 report.packageName = r.info.packageName;
7278 report.installerPackageName = r.errorReportReceiver.getPackageName();
7279 report.processName = r.processName;
7280 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007281 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007282
Dan Egnorb7f03672009-12-09 16:22:32 -08007283 if (r.crashing) {
7284 report.type = ApplicationErrorReport.TYPE_CRASH;
7285 report.crashInfo = crashInfo;
7286 } else if (r.notResponding) {
7287 report.type = ApplicationErrorReport.TYPE_ANR;
7288 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007289
Dan Egnorb7f03672009-12-09 16:22:32 -08007290 report.anrInfo.activity = r.notRespondingReport.tag;
7291 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7292 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007293 }
7294
Dan Egnorb7f03672009-12-09 16:22:32 -08007295 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007296 }
7297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007298 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7299 // assume our apps are happy - lazy create the list
7300 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7301
7302 synchronized (this) {
7303
7304 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007305 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7306 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007307 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7308 // This one's in trouble, so we'll generate a report for it
7309 // crashes are higher priority (in case there's a crash *and* an anr)
7310 ActivityManager.ProcessErrorStateInfo report = null;
7311 if (app.crashing) {
7312 report = app.crashingReport;
7313 } else if (app.notResponding) {
7314 report = app.notRespondingReport;
7315 }
7316
7317 if (report != null) {
7318 if (errList == null) {
7319 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7320 }
7321 errList.add(report);
7322 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007323 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324 " crashing = " + app.crashing +
7325 " notResponding = " + app.notResponding);
7326 }
7327 }
7328 }
7329 }
7330
7331 return errList;
7332 }
7333
7334 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7335 // Lazy instantiation of list
7336 List<ActivityManager.RunningAppProcessInfo> runList = null;
7337 synchronized (this) {
7338 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007339 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7340 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7342 // Generate process state info for running application
7343 ActivityManager.RunningAppProcessInfo currApp =
7344 new ActivityManager.RunningAppProcessInfo(app.processName,
7345 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007346 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007347 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007348 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007349 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007350 if (app.persistent) {
7351 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007353 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007354 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007355 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7356 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7357 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007358 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7359 } else if (adj >= HOME_APP_ADJ) {
7360 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7361 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007362 } else if (adj >= SECONDARY_SERVER_ADJ) {
7363 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007364 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007365 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007366 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7367 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 } else if (adj >= VISIBLE_APP_ADJ) {
7369 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7370 } else {
7371 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7372 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007373 currApp.importanceReasonCode = app.adjTypeCode;
7374 if (app.adjSource instanceof ProcessRecord) {
7375 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007376 } else if (app.adjSource instanceof ActivityRecord) {
7377 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007378 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7379 }
7380 if (app.adjTarget instanceof ComponentName) {
7381 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7382 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007383 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384 // + " lru=" + currApp.lru);
7385 if (runList == null) {
7386 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7387 }
7388 runList.add(currApp);
7389 }
7390 }
7391 }
7392 return runList;
7393 }
7394
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007395 public List<ApplicationInfo> getRunningExternalApplications() {
7396 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7397 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7398 if (runningApps != null && runningApps.size() > 0) {
7399 Set<String> extList = new HashSet<String>();
7400 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7401 if (app.pkgList != null) {
7402 for (String pkg : app.pkgList) {
7403 extList.add(pkg);
7404 }
7405 }
7406 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007407 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007408 for (String pkg : extList) {
7409 try {
7410 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7411 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7412 retList.add(info);
7413 }
7414 } catch (RemoteException e) {
7415 }
7416 }
7417 }
7418 return retList;
7419 }
7420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007421 @Override
7422 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007423 if (checkCallingPermission(android.Manifest.permission.DUMP)
7424 != PackageManager.PERMISSION_GRANTED) {
7425 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7426 + Binder.getCallingPid()
7427 + ", uid=" + Binder.getCallingUid()
7428 + " without permission "
7429 + android.Manifest.permission.DUMP);
7430 return;
7431 }
7432
7433 boolean dumpAll = false;
7434
7435 int opti = 0;
7436 while (opti < args.length) {
7437 String opt = args[opti];
7438 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7439 break;
7440 }
7441 opti++;
7442 if ("-a".equals(opt)) {
7443 dumpAll = true;
7444 } else if ("-h".equals(opt)) {
7445 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007446 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007447 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007448 pw.println(" a[ctivities]: activity stack state");
7449 pw.println(" b[roadcasts]: broadcast state");
7450 pw.println(" i[ntents]: pending intent state");
7451 pw.println(" p[rocesses]: process state");
7452 pw.println(" o[om]: out of memory management");
7453 pw.println(" prov[iders]: content provider state");
7454 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007455 pw.println(" service [name]: service client-side state");
Dianne Hackborn30d71892010-12-11 10:37:55 -08007456 pw.println(" cmd may also be a component name (com.foo/.myApp),");
7457 pw.println(" a partial substring in a component name, or an");
7458 pw.println(" ActivityRecord hex object identifier.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007459 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007460 } else {
7461 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007462 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007463 }
7464
7465 // Is the caller requesting to dump a particular piece of data?
7466 if (opti < args.length) {
7467 String cmd = args[opti];
7468 opti++;
7469 if ("activities".equals(cmd) || "a".equals(cmd)) {
7470 synchronized (this) {
7471 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007472 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007473 return;
7474 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7475 synchronized (this) {
7476 dumpBroadcastsLocked(fd, pw, args, opti, true);
7477 }
7478 return;
7479 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7480 synchronized (this) {
7481 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7482 }
7483 return;
7484 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7485 synchronized (this) {
7486 dumpProcessesLocked(fd, pw, args, opti, true);
7487 }
7488 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007489 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7490 synchronized (this) {
7491 dumpOomLocked(fd, pw, args, opti, true);
7492 }
7493 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007494 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7495 synchronized (this) {
7496 dumpProvidersLocked(fd, pw, args, opti, true);
7497 }
7498 return;
7499 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007500 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007501 return;
7502 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7503 synchronized (this) {
7504 dumpServicesLocked(fd, pw, args, opti, true);
7505 }
7506 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007507 } else {
7508 // Dumping a single activity?
7509 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7510 return;
7511 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007512 pw.println("Bad activity command, or no activities match: " + cmd);
7513 pw.println("Use -h for help.");
7514 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007516 }
7517
7518 // No piece of data specified, dump everything.
7519 synchronized (this) {
7520 boolean needSep;
7521 if (dumpAll) {
7522 pw.println("Providers in Current Activity Manager State:");
7523 }
7524 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7525 if (needSep) {
7526 pw.println(" ");
7527 }
7528 if (dumpAll) {
7529 pw.println("-------------------------------------------------------------------------------");
7530 pw.println("Broadcasts in Current Activity Manager State:");
7531 }
7532 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7533 if (needSep) {
7534 pw.println(" ");
7535 }
7536 if (dumpAll) {
7537 pw.println("-------------------------------------------------------------------------------");
7538 pw.println("Services in Current Activity Manager State:");
7539 }
7540 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7541 if (needSep) {
7542 pw.println(" ");
7543 }
7544 if (dumpAll) {
7545 pw.println("-------------------------------------------------------------------------------");
7546 pw.println("PendingIntents in Current Activity Manager State:");
7547 }
7548 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7549 if (needSep) {
7550 pw.println(" ");
7551 }
7552 if (dumpAll) {
7553 pw.println("-------------------------------------------------------------------------------");
7554 pw.println("Activities in Current Activity Manager State:");
7555 }
7556 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7557 if (needSep) {
7558 pw.println(" ");
7559 }
7560 if (dumpAll) {
7561 pw.println("-------------------------------------------------------------------------------");
7562 pw.println("Processes in Current Activity Manager State:");
7563 }
7564 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7565 }
7566 }
7567
7568 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7569 int opti, boolean dumpAll, boolean needHeader) {
7570 if (needHeader) {
7571 pw.println(" Activity stack:");
7572 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007573 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007574 pw.println(" ");
7575 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007576 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7577 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007578 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007579 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007580 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007581 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007582 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007584 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007585 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007586 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007587 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7588 pw.println(" ");
7589 pw.println(" Activities waiting to sleep:");
7590 dumpHistoryList(pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false);
7591 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007592 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007593 pw.println(" ");
7594 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007595 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007596 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007597
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007598 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007599 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7600 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007601 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007602 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007603 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007604
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007605 if (dumpAll && mRecentTasks.size() > 0) {
7606 pw.println(" ");
7607 pw.println("Recent tasks in Current Activity Manager State:");
7608
7609 final int N = mRecentTasks.size();
7610 for (int i=0; i<N; i++) {
7611 TaskRecord tr = mRecentTasks.get(i);
7612 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7613 pw.println(tr);
7614 mRecentTasks.get(i).dump(pw, " ");
7615 }
7616 }
7617
7618 pw.println(" ");
7619 pw.println(" mCurTask: " + mCurTask);
7620
7621 return true;
7622 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007623
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007624 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7625 int opti, boolean dumpAll) {
7626 boolean needSep = false;
7627 int numPers = 0;
7628
7629 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007630 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7631 final int NA = procs.size();
7632 for (int ia=0; ia<NA; ia++) {
7633 if (!needSep) {
7634 pw.println(" All known processes:");
7635 needSep = true;
7636 }
7637 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007638 pw.print(r.persistent ? " *PERS*" : " *APP*");
7639 pw.print(" UID "); pw.print(procs.keyAt(ia));
7640 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007641 r.dump(pw, " ");
7642 if (r.persistent) {
7643 numPers++;
7644 }
7645 }
7646 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007647 }
7648
7649 if (mLruProcesses.size() > 0) {
7650 if (needSep) pw.println(" ");
7651 needSep = true;
7652 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007653 dumpProcessOomList(pw, this, mLruProcesses, " ",
7654 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007655 needSep = true;
7656 }
7657
7658 synchronized (mPidsSelfLocked) {
7659 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007660 if (needSep) pw.println(" ");
7661 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007662 pw.println(" PID mappings:");
7663 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7664 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7665 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666 }
7667 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007668 }
7669
7670 if (mForegroundProcesses.size() > 0) {
7671 if (needSep) pw.println(" ");
7672 needSep = true;
7673 pw.println(" Foreground Processes:");
7674 for (int i=0; i<mForegroundProcesses.size(); i++) {
7675 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7676 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007677 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007678 }
7679
7680 if (mPersistentStartingProcesses.size() > 0) {
7681 if (needSep) pw.println(" ");
7682 needSep = true;
7683 pw.println(" Persisent processes that are starting:");
7684 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007685 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007687
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007688 if (mStartingProcesses.size() > 0) {
7689 if (needSep) pw.println(" ");
7690 needSep = true;
7691 pw.println(" Processes that are starting:");
7692 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007693 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007695
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007696 if (mRemovedProcesses.size() > 0) {
7697 if (needSep) pw.println(" ");
7698 needSep = true;
7699 pw.println(" Processes that are being removed:");
7700 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007701 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007702 }
7703
7704 if (mProcessesOnHold.size() > 0) {
7705 if (needSep) pw.println(" ");
7706 needSep = true;
7707 pw.println(" Processes that are on old until the system is ready:");
7708 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007709 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007711
Dianne Hackborn287952c2010-09-22 22:34:31 -07007712 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007713
7714 if (mProcessCrashTimes.getMap().size() > 0) {
7715 if (needSep) pw.println(" ");
7716 needSep = true;
7717 pw.println(" Time since processes crashed:");
7718 long now = SystemClock.uptimeMillis();
7719 for (Map.Entry<String, SparseArray<Long>> procs
7720 : mProcessCrashTimes.getMap().entrySet()) {
7721 SparseArray<Long> uids = procs.getValue();
7722 final int N = uids.size();
7723 for (int i=0; i<N; i++) {
7724 pw.print(" Process "); pw.print(procs.getKey());
7725 pw.print(" uid "); pw.print(uids.keyAt(i));
7726 pw.print(": last crashed ");
7727 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007728 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007729 }
7730 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007732
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007733 if (mBadProcesses.getMap().size() > 0) {
7734 if (needSep) pw.println(" ");
7735 needSep = true;
7736 pw.println(" Bad processes:");
7737 for (Map.Entry<String, SparseArray<Long>> procs
7738 : mBadProcesses.getMap().entrySet()) {
7739 SparseArray<Long> uids = procs.getValue();
7740 final int N = uids.size();
7741 for (int i=0; i<N; i++) {
7742 pw.print(" Bad process "); pw.print(procs.getKey());
7743 pw.print(" uid "); pw.print(uids.keyAt(i));
7744 pw.print(": crashed at time ");
7745 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007746 }
7747 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007748 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007749
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007750 pw.println(" ");
7751 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007752 if (mHeavyWeightProcess != null) {
7753 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7754 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007755 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007756 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007757 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7758 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7759 || mOrigWaitForDebugger) {
7760 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7761 + " mDebugTransient=" + mDebugTransient
7762 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7763 }
7764 if (mAlwaysFinishActivities || mController != null) {
7765 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7766 + " mController=" + mController);
7767 }
7768 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007769 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007770 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007771 + " mProcessesReady=" + mProcessesReady
7772 + " mSystemReady=" + mSystemReady);
7773 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774 + " mBooted=" + mBooted
7775 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007776 pw.print(" mLastPowerCheckRealtime=");
7777 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7778 pw.println("");
7779 pw.print(" mLastPowerCheckUptime=");
7780 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7781 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007782 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7783 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007784 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007786
7787 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007788 }
7789
Dianne Hackborn287952c2010-09-22 22:34:31 -07007790 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7791 int opti, boolean needSep, boolean dumpAll) {
7792 if (mProcessesToGc.size() > 0) {
7793 if (needSep) pw.println(" ");
7794 needSep = true;
7795 pw.println(" Processes that are waiting to GC:");
7796 long now = SystemClock.uptimeMillis();
7797 for (int i=0; i<mProcessesToGc.size(); i++) {
7798 ProcessRecord proc = mProcessesToGc.get(i);
7799 pw.print(" Process "); pw.println(proc);
7800 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7801 pw.print(", last gced=");
7802 pw.print(now-proc.lastRequestedGc);
7803 pw.print(" ms ago, last lowMem=");
7804 pw.print(now-proc.lastLowMemory);
7805 pw.println(" ms ago");
7806
7807 }
7808 }
7809 return needSep;
7810 }
7811
7812 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7813 int opti, boolean dumpAll) {
7814 boolean needSep = false;
7815
7816 if (mLruProcesses.size() > 0) {
7817 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7818
7819 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7820 @Override
7821 public int compare(ProcessRecord object1, ProcessRecord object2) {
7822 if (object1.setAdj != object2.setAdj) {
7823 return object1.setAdj > object2.setAdj ? -1 : 1;
7824 }
7825 if (object1.setSchedGroup != object2.setSchedGroup) {
7826 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7827 }
7828 if (object1.keeping != object2.keeping) {
7829 return object1.keeping ? -1 : 1;
7830 }
7831 if (object1.pid != object2.pid) {
7832 return object1.pid > object2.pid ? -1 : 1;
7833 }
7834 return 0;
7835 }
7836 };
7837
7838 Collections.sort(procs, comparator);
7839
7840 if (needSep) pw.println(" ");
7841 needSep = true;
7842 pw.println(" Process OOM control:");
7843 dumpProcessOomList(pw, this, procs, " ",
7844 "Proc", "PERS", true);
7845 needSep = true;
7846 }
7847
7848 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7849
7850 pw.println(" ");
7851 pw.println(" mHomeProcess: " + mHomeProcess);
7852 if (mHeavyWeightProcess != null) {
7853 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7854 }
7855
7856 return true;
7857 }
7858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007859 /**
7860 * There are three ways to call this:
7861 * - no service specified: dump all the services
7862 * - a flattened component name that matched an existing service was specified as the
7863 * first arg: dump that one service
7864 * - the first arg isn't the flattened component name of an existing service:
7865 * dump all services whose component contains the first arg as a substring
7866 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007867 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007868 String[] newArgs;
7869 String componentNameString;
7870 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007871 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007872 componentNameString = null;
7873 newArgs = EMPTY_STRING_ARRAY;
7874 r = null;
7875 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007876 componentNameString = args[opti];
7877 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007878 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007879 synchronized (this) {
7880 r = componentName != null ? mServices.get(componentName) : null;
7881 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007882 newArgs = new String[args.length - opti];
7883 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007884 }
7885
7886 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007887 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007888 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007889 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7890 synchronized (this) {
7891 for (ServiceRecord r1 : mServices.values()) {
7892 if (componentNameString == null
7893 || r1.name.flattenToString().contains(componentNameString)) {
7894 services.add(r1);
7895 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007896 }
7897 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007898 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007899 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901 }
7902 }
7903
7904 /**
7905 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7906 * there is a thread associated with the service.
7907 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007908 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7909 pw.println("------------------------------------------------------------"
7910 + "-------------------");
7911 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007912 if (r.app != null && r.app.thread != null) {
7913 try {
7914 // flush anything that is already in the PrintWriter since the thread is going
7915 // to write to the file descriptor directly
7916 pw.flush();
7917 r.app.thread.dumpService(fd, r, args);
7918 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007919 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007920 } catch (RemoteException e) {
7921 pw.println("got a RemoteException while dumping the service");
7922 }
7923 }
7924 }
7925
Dianne Hackborn625ac272010-09-17 18:29:22 -07007926 /**
7927 * There are three things that cmd can be:
7928 * - a flattened component name that matched an existing activity
7929 * - the cmd arg isn't the flattened component name of an existing activity:
7930 * dump all activity whose component contains the cmd as a substring
7931 * - A hex number of the ActivityRecord object instance.
7932 */
7933 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7934 int opti, boolean dumpAll) {
7935 String[] newArgs;
7936 ComponentName componentName = ComponentName.unflattenFromString(name);
7937 int objectId = 0;
Dianne Hackborn30d71892010-12-11 10:37:55 -08007938 if (componentName == null) {
7939 // Not a '/' separated full component name; maybe an object ID?
7940 try {
7941 objectId = Integer.parseInt(name, 16);
7942 name = null;
7943 componentName = null;
7944 } catch (RuntimeException e) {
7945 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007946 }
7947 newArgs = new String[args.length - opti];
7948 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7949
7950 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7951 synchronized (this) {
7952 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7953 if (componentName != null) {
7954 if (r1.intent.getComponent().equals(componentName)) {
7955 activities.add(r1);
7956 }
7957 } else if (name != null) {
7958 if (r1.intent.getComponent().flattenToString().contains(name)) {
7959 activities.add(r1);
7960 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007961 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07007962 activities.add(r1);
7963 }
7964 }
7965 }
7966
7967 if (activities.size() <= 0) {
7968 return false;
7969 }
7970
Dianne Hackborn30d71892010-12-11 10:37:55 -08007971 TaskRecord lastTask = null;
7972 for (int i=activities.size()-1; i>=0; i--) {
7973 ActivityRecord r = (ActivityRecord)activities.get(i);
7974 if (lastTask != r.task) {
7975 lastTask = r.task;
7976 pw.print("* Task "); pw.print(lastTask.affinity);
7977 pw.print(" id="); pw.println(lastTask.taskId);
7978 if (dumpAll) {
7979 lastTask.dump(pw, " ");
7980 }
7981 }
7982 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007983 }
7984 return true;
7985 }
7986
7987 /**
7988 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7989 * there is a thread associated with the activity.
7990 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08007991 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
7992 ActivityRecord r, String[] args, boolean dumpAll) {
7993 synchronized (this) {
7994 pw.print(prefix); pw.print("* Activity ");
7995 pw.print(Integer.toHexString(System.identityHashCode(r)));
7996 pw.print(" "); pw.print(r.shortComponentName); pw.print(" pid=");
7997 if (r.app != null) pw.println(r.app.pid);
7998 else pw.println("(not running)");
7999 if (dumpAll) {
8000 r.dump(pw, prefix + " ");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008001 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008002 }
8003 if (r.app != null && r.app.thread != null) {
8004 try {
8005 // flush anything that is already in the PrintWriter since the thread is going
8006 // to write to the file descriptor directly
8007 pw.flush();
Dianne Hackborn30d71892010-12-11 10:37:55 -08008008 r.app.thread.dumpActivity(fd, r, prefix + " ", args);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008009 pw.flush();
8010 } catch (RemoteException e) {
8011 pw.println("got a RemoteException while dumping the activity");
8012 }
8013 }
8014 }
8015
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008016 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8017 int opti, boolean dumpAll) {
8018 boolean needSep = false;
8019
8020 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021 if (mRegisteredReceivers.size() > 0) {
8022 pw.println(" ");
8023 pw.println(" Registered Receivers:");
8024 Iterator it = mRegisteredReceivers.values().iterator();
8025 while (it.hasNext()) {
8026 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008027 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008028 r.dump(pw, " ");
8029 }
8030 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 pw.println(" ");
8033 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008034 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008035 needSep = true;
8036 }
8037
8038 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8039 || mPendingBroadcast != null) {
8040 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008041 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008042 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008043 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008044 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8045 pw.println(" Broadcast #" + i + ":");
8046 mParallelBroadcasts.get(i).dump(pw, " ");
8047 }
8048 if (mOrderedBroadcasts.size() > 0) {
8049 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008050 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008051 }
8052 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8053 pw.println(" Serialized Broadcast #" + i + ":");
8054 mOrderedBroadcasts.get(i).dump(pw, " ");
8055 }
8056 pw.println(" ");
8057 pw.println(" Pending broadcast:");
8058 if (mPendingBroadcast != null) {
8059 mPendingBroadcast.dump(pw, " ");
8060 } else {
8061 pw.println(" (null)");
8062 }
8063 needSep = true;
8064 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008065
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008066 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008067 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008068 pw.println(" Historical broadcasts:");
8069 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8070 BroadcastRecord r = mBroadcastHistory[i];
8071 if (r == null) {
8072 break;
8073 }
8074 pw.println(" Historical Broadcast #" + i + ":");
8075 r.dump(pw, " ");
8076 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008077 needSep = true;
8078 }
8079
8080 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08008081 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008082 pw.println(" Sticky broadcasts:");
8083 StringBuilder sb = new StringBuilder(128);
8084 for (Map.Entry<String, ArrayList<Intent>> ent
8085 : mStickyBroadcasts.entrySet()) {
8086 pw.print(" * Sticky action "); pw.print(ent.getKey());
8087 pw.println(":");
8088 ArrayList<Intent> intents = ent.getValue();
8089 final int N = intents.size();
8090 for (int i=0; i<N; i++) {
8091 sb.setLength(0);
8092 sb.append(" Intent: ");
8093 intents.get(i).toShortString(sb, true, false);
8094 pw.println(sb.toString());
8095 Bundle bundle = intents.get(i).getExtras();
8096 if (bundle != null) {
8097 pw.print(" ");
8098 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008099 }
8100 }
8101 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008102 needSep = true;
8103 }
8104
8105 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008106 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008107 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008108 pw.println(" mHandler:");
8109 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008110 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008111 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008112
8113 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008114 }
8115
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008116 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8117 int opti, boolean dumpAll) {
8118 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008119
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008120 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008121 if (mServices.size() > 0) {
8122 pw.println(" Active services:");
8123 Iterator<ServiceRecord> it = mServices.values().iterator();
8124 while (it.hasNext()) {
8125 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008126 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008127 r.dump(pw, " ");
8128 }
8129 needSep = true;
8130 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008132
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008133 if (mPendingServices.size() > 0) {
8134 if (needSep) pw.println(" ");
8135 pw.println(" Pending services:");
8136 for (int i=0; i<mPendingServices.size(); i++) {
8137 ServiceRecord r = mPendingServices.get(i);
8138 pw.print(" * Pending "); pw.println(r);
8139 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008140 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008141 needSep = true;
8142 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008143
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008144 if (mRestartingServices.size() > 0) {
8145 if (needSep) pw.println(" ");
8146 pw.println(" Restarting services:");
8147 for (int i=0; i<mRestartingServices.size(); i++) {
8148 ServiceRecord r = mRestartingServices.get(i);
8149 pw.print(" * Restarting "); pw.println(r);
8150 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008151 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008152 needSep = true;
8153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008154
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008155 if (mStoppingServices.size() > 0) {
8156 if (needSep) pw.println(" ");
8157 pw.println(" Stopping services:");
8158 for (int i=0; i<mStoppingServices.size(); i++) {
8159 ServiceRecord r = mStoppingServices.get(i);
8160 pw.print(" * Stopping "); pw.println(r);
8161 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008163 needSep = true;
8164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008166 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008167 if (mServiceConnections.size() > 0) {
8168 if (needSep) pw.println(" ");
8169 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008170 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008171 = mServiceConnections.values().iterator();
8172 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008173 ArrayList<ConnectionRecord> r = it.next();
8174 for (int i=0; i<r.size(); i++) {
8175 pw.print(" * "); pw.println(r.get(i));
8176 r.get(i).dump(pw, " ");
8177 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008178 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008179 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008180 }
8181 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008182
8183 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008184 }
8185
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008186 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8187 int opti, boolean dumpAll) {
8188 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008189
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008190 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008191 if (mProvidersByClass.size() > 0) {
8192 if (needSep) pw.println(" ");
8193 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008194 Iterator<Map.Entry<String, ContentProviderRecord>> it
8195 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008196 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008197 Map.Entry<String, ContentProviderRecord> e = it.next();
8198 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008199 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008200 r.dump(pw, " ");
8201 }
8202 needSep = true;
8203 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008204
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008205 if (mProvidersByName.size() > 0) {
8206 pw.println(" ");
8207 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008208 Iterator<Map.Entry<String, ContentProviderRecord>> it
8209 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008210 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008211 Map.Entry<String, ContentProviderRecord> e = it.next();
8212 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008213 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8214 pw.println(r);
8215 }
8216 needSep = true;
8217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008218 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008219
8220 if (mLaunchingProviders.size() > 0) {
8221 if (needSep) pw.println(" ");
8222 pw.println(" Launching content providers:");
8223 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8224 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8225 pw.println(mLaunchingProviders.get(i));
8226 }
8227 needSep = true;
8228 }
8229
8230 if (mGrantedUriPermissions.size() > 0) {
8231 pw.println();
8232 pw.println("Granted Uri Permissions:");
8233 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8234 int uid = mGrantedUriPermissions.keyAt(i);
8235 HashMap<Uri, UriPermission> perms
8236 = mGrantedUriPermissions.valueAt(i);
8237 pw.print(" * UID "); pw.print(uid);
8238 pw.println(" holds:");
8239 for (UriPermission perm : perms.values()) {
8240 pw.print(" "); pw.println(perm);
8241 perm.dump(pw, " ");
8242 }
8243 }
8244 needSep = true;
8245 }
8246
8247 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008248 }
8249
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008250 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8251 int opti, boolean dumpAll) {
8252 boolean needSep = false;
8253
8254 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008255 if (this.mIntentSenderRecords.size() > 0) {
8256 Iterator<WeakReference<PendingIntentRecord>> it
8257 = mIntentSenderRecords.values().iterator();
8258 while (it.hasNext()) {
8259 WeakReference<PendingIntentRecord> ref = it.next();
8260 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008261 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008262 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008263 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008264 rec.dump(pw, " ");
8265 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008266 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008267 }
8268 }
8269 }
8270 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008271
8272 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008273 }
8274
8275 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008276 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008277 TaskRecord lastTask = null;
8278 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008279 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008280 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008281 if (lastTask != r.task) {
8282 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008283 pw.print(prefix);
8284 pw.print(full ? "* " : " ");
8285 pw.println(lastTask);
8286 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008287 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008289 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008290 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8291 pw.print(" #"); pw.print(i); pw.print(": ");
8292 pw.println(r);
8293 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008294 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008296 }
8297 }
8298
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008299 private static String buildOomTag(String prefix, String space, int val, int base) {
8300 if (val == base) {
8301 if (space == null) return prefix;
8302 return prefix + " ";
8303 }
8304 return prefix + "+" + Integer.toString(val-base);
8305 }
8306
8307 private static final int dumpProcessList(PrintWriter pw,
8308 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008309 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008310 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008311 final int N = list.size()-1;
8312 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008313 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008314 pw.println(String.format("%s%s #%2d: %s",
8315 prefix, (r.persistent ? persistentLabel : normalLabel),
8316 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008317 if (r.persistent) {
8318 numPers++;
8319 }
8320 }
8321 return numPers;
8322 }
8323
Dianne Hackborn287952c2010-09-22 22:34:31 -07008324 private static final void dumpProcessOomList(PrintWriter pw,
8325 ActivityManagerService service, List<ProcessRecord> list,
8326 String prefix, String normalLabel, String persistentLabel,
8327 boolean inclDetails) {
8328
8329 final long curRealtime = SystemClock.elapsedRealtime();
8330 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8331 final long curUptime = SystemClock.uptimeMillis();
8332 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8333
8334 final int N = list.size()-1;
8335 for (int i=N; i>=0; i--) {
8336 ProcessRecord r = list.get(i);
8337 String oomAdj;
8338 if (r.setAdj >= EMPTY_APP_ADJ) {
8339 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8340 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8341 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8342 } else if (r.setAdj >= HOME_APP_ADJ) {
8343 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8344 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8345 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8346 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8347 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8348 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8349 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8350 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8351 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8352 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8353 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8354 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8355 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8356 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8357 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8358 } else if (r.setAdj >= SYSTEM_ADJ) {
8359 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8360 } else {
8361 oomAdj = Integer.toString(r.setAdj);
8362 }
8363 String schedGroup;
8364 switch (r.setSchedGroup) {
8365 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8366 schedGroup = "B";
8367 break;
8368 case Process.THREAD_GROUP_DEFAULT:
8369 schedGroup = "F";
8370 break;
8371 default:
8372 schedGroup = Integer.toString(r.setSchedGroup);
8373 break;
8374 }
8375 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8376 prefix, (r.persistent ? persistentLabel : normalLabel),
8377 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8378 if (r.adjSource != null || r.adjTarget != null) {
8379 pw.print(prefix);
8380 pw.print(" ");
8381 if (r.adjTarget instanceof ComponentName) {
8382 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8383 } else if (r.adjTarget != null) {
8384 pw.print(r.adjTarget.toString());
8385 } else {
8386 pw.print("{null}");
8387 }
8388 pw.print("<=");
8389 if (r.adjSource instanceof ProcessRecord) {
8390 pw.print("Proc{");
8391 pw.print(((ProcessRecord)r.adjSource).toShortString());
8392 pw.println("}");
8393 } else if (r.adjSource != null) {
8394 pw.println(r.adjSource.toString());
8395 } else {
8396 pw.println("{null}");
8397 }
8398 }
8399 if (inclDetails) {
8400 pw.print(prefix);
8401 pw.print(" ");
8402 pw.print("oom: max="); pw.print(r.maxAdj);
8403 pw.print(" hidden="); pw.print(r.hiddenAdj);
8404 pw.print(" curRaw="); pw.print(r.curRawAdj);
8405 pw.print(" setRaw="); pw.print(r.setRawAdj);
8406 pw.print(" cur="); pw.print(r.curAdj);
8407 pw.print(" set="); pw.println(r.setAdj);
8408 pw.print(prefix);
8409 pw.print(" ");
8410 pw.print("keeping="); pw.print(r.keeping);
8411 pw.print(" hidden="); pw.print(r.hidden);
8412 pw.print(" empty="); pw.println(r.empty);
8413
8414 if (!r.keeping) {
8415 if (r.lastWakeTime != 0) {
8416 long wtime;
8417 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8418 synchronized (stats) {
8419 wtime = stats.getProcessWakeTime(r.info.uid,
8420 r.pid, curRealtime);
8421 }
8422 long timeUsed = wtime - r.lastWakeTime;
8423 pw.print(prefix);
8424 pw.print(" ");
8425 pw.print("keep awake over ");
8426 TimeUtils.formatDuration(realtimeSince, pw);
8427 pw.print(" used ");
8428 TimeUtils.formatDuration(timeUsed, pw);
8429 pw.print(" (");
8430 pw.print((timeUsed*100)/realtimeSince);
8431 pw.println("%)");
8432 }
8433 if (r.lastCpuTime != 0) {
8434 long timeUsed = r.curCpuTime - r.lastCpuTime;
8435 pw.print(prefix);
8436 pw.print(" ");
8437 pw.print("run cpu over ");
8438 TimeUtils.formatDuration(uptimeSince, pw);
8439 pw.print(" used ");
8440 TimeUtils.formatDuration(timeUsed, pw);
8441 pw.print(" (");
8442 pw.print((timeUsed*100)/uptimeSince);
8443 pw.println("%)");
8444 }
8445 }
8446 }
8447 }
8448 }
8449
Dianne Hackborn472ad872010-04-07 17:31:48 -07008450 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008451 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008452 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008453 long uptime = SystemClock.uptimeMillis();
8454 long realtime = SystemClock.elapsedRealtime();
8455
8456 if (isCheckinRequest) {
8457 // short checkin version
8458 pw.println(uptime + "," + realtime);
8459 pw.flush();
8460 } else {
8461 pw.println("Applications Memory Usage (kB):");
8462 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8463 }
8464 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8465 ProcessRecord r = (ProcessRecord)list.get(i);
8466 if (r.thread != null) {
8467 if (!isCheckinRequest) {
8468 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8469 pw.flush();
8470 }
8471 try {
8472 r.thread.asBinder().dump(fd, args);
8473 } catch (RemoteException e) {
8474 if (!isCheckinRequest) {
8475 pw.println("Got RemoteException!");
8476 pw.flush();
8477 }
8478 }
8479 }
8480 }
8481 }
8482
8483 /**
8484 * Searches array of arguments for the specified string
8485 * @param args array of argument strings
8486 * @param value value to search for
8487 * @return true if the value is contained in the array
8488 */
8489 private static boolean scanArgs(String[] args, String value) {
8490 if (args != null) {
8491 for (String arg : args) {
8492 if (value.equals(arg)) {
8493 return true;
8494 }
8495 }
8496 }
8497 return false;
8498 }
8499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008500 private final void killServicesLocked(ProcessRecord app,
8501 boolean allowRestart) {
8502 // Report disconnected services.
8503 if (false) {
8504 // XXX we are letting the client link to the service for
8505 // death notifications.
8506 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008507 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008508 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008509 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008510 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008511 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008512 = r.connections.values().iterator();
8513 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008514 ArrayList<ConnectionRecord> cl = jt.next();
8515 for (int i=0; i<cl.size(); i++) {
8516 ConnectionRecord c = cl.get(i);
8517 if (c.binding.client != app) {
8518 try {
8519 //c.conn.connected(r.className, null);
8520 } catch (Exception e) {
8521 // todo: this should be asynchronous!
8522 Slog.w(TAG, "Exception thrown disconnected servce "
8523 + r.shortName
8524 + " from app " + app.processName, e);
8525 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008526 }
8527 }
8528 }
8529 }
8530 }
8531 }
8532 }
8533
8534 // Clean up any connections this application has to other services.
8535 if (app.connections.size() > 0) {
8536 Iterator<ConnectionRecord> it = app.connections.iterator();
8537 while (it.hasNext()) {
8538 ConnectionRecord r = it.next();
8539 removeConnectionLocked(r, app, null);
8540 }
8541 }
8542 app.connections.clear();
8543
8544 if (app.services.size() != 0) {
8545 // Any services running in the application need to be placed
8546 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008547 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008548 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008549 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008550 synchronized (sr.stats.getBatteryStats()) {
8551 sr.stats.stopLaunchedLocked();
8552 }
8553 sr.app = null;
8554 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008555 if (mStoppingServices.remove(sr)) {
8556 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8557 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008558
8559 boolean hasClients = sr.bindings.size() > 0;
8560 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008561 Iterator<IntentBindRecord> bindings
8562 = sr.bindings.values().iterator();
8563 while (bindings.hasNext()) {
8564 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008565 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008566 + ": shouldUnbind=" + b.hasBound);
8567 b.binder = null;
8568 b.requested = b.received = b.hasBound = false;
8569 }
8570 }
8571
Dianne Hackborn070783f2010-12-29 16:46:28 -08008572 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
8573 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008574 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008575 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008576 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008577 sr.crashCount, sr.shortName, app.pid);
8578 bringDownServiceLocked(sr, true);
8579 } else if (!allowRestart) {
8580 bringDownServiceLocked(sr, true);
8581 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008582 boolean canceled = scheduleServiceRestartLocked(sr, true);
8583
8584 // Should the service remain running? Note that in the
8585 // extreme case of so many attempts to deliver a command
8586 // that it failed, that we also will stop it here.
8587 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8588 if (sr.pendingStarts.size() == 0) {
8589 sr.startRequested = false;
8590 if (!hasClients) {
8591 // Whoops, no reason to restart!
8592 bringDownServiceLocked(sr, true);
8593 }
8594 }
8595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008596 }
8597 }
8598
8599 if (!allowRestart) {
8600 app.services.clear();
8601 }
8602 }
8603
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008604 // Make sure we have no more records on the stopping list.
8605 int i = mStoppingServices.size();
8606 while (i > 0) {
8607 i--;
8608 ServiceRecord sr = mStoppingServices.get(i);
8609 if (sr.app == app) {
8610 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008611 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008612 }
8613 }
8614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008615 app.executingServices.clear();
8616 }
8617
8618 private final void removeDyingProviderLocked(ProcessRecord proc,
8619 ContentProviderRecord cpr) {
8620 synchronized (cpr) {
8621 cpr.launchingApp = null;
8622 cpr.notifyAll();
8623 }
8624
8625 mProvidersByClass.remove(cpr.info.name);
8626 String names[] = cpr.info.authority.split(";");
8627 for (int j = 0; j < names.length; j++) {
8628 mProvidersByName.remove(names[j]);
8629 }
8630
8631 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8632 while (cit.hasNext()) {
8633 ProcessRecord capp = cit.next();
8634 if (!capp.persistent && capp.thread != null
8635 && capp.pid != 0
8636 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008637 Slog.i(TAG, "Kill " + capp.processName
8638 + " (pid " + capp.pid + "): provider " + cpr.info.name
8639 + " in dying process " + proc.processName);
8640 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8641 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008642 Process.killProcess(capp.pid);
8643 }
8644 }
8645
8646 mLaunchingProviders.remove(cpr);
8647 }
8648
8649 /**
8650 * Main code for cleaning up a process when it has gone away. This is
8651 * called both as a result of the process dying, or directly when stopping
8652 * a process when running in single process mode.
8653 */
8654 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8655 boolean restarting, int index) {
8656 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008657 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008658 }
8659
Dianne Hackborn36124872009-10-08 16:22:03 -07008660 mProcessesToGc.remove(app);
8661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008662 // Dismiss any open dialogs.
8663 if (app.crashDialog != null) {
8664 app.crashDialog.dismiss();
8665 app.crashDialog = null;
8666 }
8667 if (app.anrDialog != null) {
8668 app.anrDialog.dismiss();
8669 app.anrDialog = null;
8670 }
8671 if (app.waitDialog != null) {
8672 app.waitDialog.dismiss();
8673 app.waitDialog = null;
8674 }
8675
8676 app.crashing = false;
8677 app.notResponding = false;
8678
8679 app.resetPackageList();
8680 app.thread = null;
8681 app.forcingToForeground = null;
8682 app.foregroundServices = false;
8683
8684 killServicesLocked(app, true);
8685
8686 boolean restart = false;
8687
8688 int NL = mLaunchingProviders.size();
8689
8690 // Remove published content providers.
8691 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008692 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008693 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008694 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008695 cpr.provider = null;
8696 cpr.app = null;
8697
8698 // See if someone is waiting for this provider... in which
8699 // case we don't remove it, but just let it restart.
8700 int i = 0;
8701 if (!app.bad) {
8702 for (; i<NL; i++) {
8703 if (mLaunchingProviders.get(i) == cpr) {
8704 restart = true;
8705 break;
8706 }
8707 }
8708 } else {
8709 i = NL;
8710 }
8711
8712 if (i >= NL) {
8713 removeDyingProviderLocked(app, cpr);
8714 NL = mLaunchingProviders.size();
8715 }
8716 }
8717 app.pubProviders.clear();
8718 }
8719
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008720 // Take care of any launching providers waiting for this process.
8721 if (checkAppInLaunchingProvidersLocked(app, false)) {
8722 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008723 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008724
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008725 // Unregister from connected content providers.
8726 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008727 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008728 while (it.hasNext()) {
8729 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8730 cpr.clients.remove(app);
8731 }
8732 app.conProviders.clear();
8733 }
8734
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008735 // At this point there may be remaining entries in mLaunchingProviders
8736 // where we were the only one waiting, so they are no longer of use.
8737 // Look for these and clean up if found.
8738 // XXX Commented out for now. Trying to figure out a way to reproduce
8739 // the actual situation to identify what is actually going on.
8740 if (false) {
8741 for (int i=0; i<NL; i++) {
8742 ContentProviderRecord cpr = (ContentProviderRecord)
8743 mLaunchingProviders.get(i);
8744 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8745 synchronized (cpr) {
8746 cpr.launchingApp = null;
8747 cpr.notifyAll();
8748 }
8749 }
8750 }
8751 }
8752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008753 skipCurrentReceiverLocked(app);
8754
8755 // Unregister any receivers.
8756 if (app.receivers.size() > 0) {
8757 Iterator<ReceiverList> it = app.receivers.iterator();
8758 while (it.hasNext()) {
8759 removeReceiverLocked(it.next());
8760 }
8761 app.receivers.clear();
8762 }
8763
Christopher Tate181fafa2009-05-14 11:12:14 -07008764 // If the app is undergoing backup, tell the backup manager about it
8765 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008766 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008767 try {
8768 IBackupManager bm = IBackupManager.Stub.asInterface(
8769 ServiceManager.getService(Context.BACKUP_SERVICE));
8770 bm.agentDisconnected(app.info.packageName);
8771 } catch (RemoteException e) {
8772 // can't happen; backup manager is local
8773 }
8774 }
8775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008776 // If the caller is restarting this app, then leave it in its
8777 // current lists and let the caller take care of it.
8778 if (restarting) {
8779 return;
8780 }
8781
8782 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008783 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008784 "Removing non-persistent process during cleanup: " + app);
8785 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008786 if (mHeavyWeightProcess == app) {
8787 mHeavyWeightProcess = null;
8788 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008790 } else if (!app.removed) {
8791 // This app is persistent, so we need to keep its record around.
8792 // If it is not already on the pending app list, add it there
8793 // and start a new process for it.
8794 app.thread = null;
8795 app.forcingToForeground = null;
8796 app.foregroundServices = false;
8797 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8798 mPersistentStartingProcesses.add(app);
8799 restart = true;
8800 }
8801 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008802 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8803 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008804 mProcessesOnHold.remove(app);
8805
The Android Open Source Project4df24232009-03-05 14:34:35 -08008806 if (app == mHomeProcess) {
8807 mHomeProcess = null;
8808 }
8809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008810 if (restart) {
8811 // We have components that still need to be running in the
8812 // process, so re-launch it.
8813 mProcessNames.put(app.processName, app.info.uid, app);
8814 startProcessLocked(app, "restart", app.processName);
8815 } else if (app.pid > 0 && app.pid != MY_PID) {
8816 // Goodbye!
8817 synchronized (mPidsSelfLocked) {
8818 mPidsSelfLocked.remove(app.pid);
8819 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8820 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008821 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008822 }
8823 }
8824
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008825 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8826 // Look through the content providers we are waiting to have launched,
8827 // and if any run in this process then either schedule a restart of
8828 // the process or kill the client waiting for it if this process has
8829 // gone bad.
8830 int NL = mLaunchingProviders.size();
8831 boolean restart = false;
8832 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008833 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008834 if (cpr.launchingApp == app) {
8835 if (!alwaysBad && !app.bad) {
8836 restart = true;
8837 } else {
8838 removeDyingProviderLocked(app, cpr);
8839 NL = mLaunchingProviders.size();
8840 }
8841 }
8842 }
8843 return restart;
8844 }
8845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008846 // =========================================================
8847 // SERVICES
8848 // =========================================================
8849
8850 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8851 ActivityManager.RunningServiceInfo info =
8852 new ActivityManager.RunningServiceInfo();
8853 info.service = r.name;
8854 if (r.app != null) {
8855 info.pid = r.app.pid;
8856 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008857 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008858 info.process = r.processName;
8859 info.foreground = r.isForeground;
8860 info.activeSince = r.createTime;
8861 info.started = r.startRequested;
8862 info.clientCount = r.connections.size();
8863 info.crashCount = r.crashCount;
8864 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008865 if (r.isForeground) {
8866 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8867 }
8868 if (r.startRequested) {
8869 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8870 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008871 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008872 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8873 }
8874 if (r.app != null && r.app.persistent) {
8875 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8876 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008877
8878 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8879 for (int i=0; i<connl.size(); i++) {
8880 ConnectionRecord conn = connl.get(i);
8881 if (conn.clientLabel != 0) {
8882 info.clientPackage = conn.binding.client.info.packageName;
8883 info.clientLabel = conn.clientLabel;
8884 return info;
8885 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008886 }
8887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008888 return info;
8889 }
8890
8891 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8892 int flags) {
8893 synchronized (this) {
8894 ArrayList<ActivityManager.RunningServiceInfo> res
8895 = new ArrayList<ActivityManager.RunningServiceInfo>();
8896
8897 if (mServices.size() > 0) {
8898 Iterator<ServiceRecord> it = mServices.values().iterator();
8899 while (it.hasNext() && res.size() < maxNum) {
8900 res.add(makeRunningServiceInfoLocked(it.next()));
8901 }
8902 }
8903
8904 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8905 ServiceRecord r = mRestartingServices.get(i);
8906 ActivityManager.RunningServiceInfo info =
8907 makeRunningServiceInfoLocked(r);
8908 info.restarting = r.nextRestartTime;
8909 res.add(info);
8910 }
8911
8912 return res;
8913 }
8914 }
8915
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008916 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8917 synchronized (this) {
8918 ServiceRecord r = mServices.get(name);
8919 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008920 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8921 for (int i=0; i<conn.size(); i++) {
8922 if (conn.get(i).clientIntent != null) {
8923 return conn.get(i).clientIntent;
8924 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008925 }
8926 }
8927 }
8928 }
8929 return null;
8930 }
8931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008932 private final ServiceRecord findServiceLocked(ComponentName name,
8933 IBinder token) {
8934 ServiceRecord r = mServices.get(name);
8935 return r == token ? r : null;
8936 }
8937
8938 private final class ServiceLookupResult {
8939 final ServiceRecord record;
8940 final String permission;
8941
8942 ServiceLookupResult(ServiceRecord _record, String _permission) {
8943 record = _record;
8944 permission = _permission;
8945 }
8946 };
8947
8948 private ServiceLookupResult findServiceLocked(Intent service,
8949 String resolvedType) {
8950 ServiceRecord r = null;
8951 if (service.getComponent() != null) {
8952 r = mServices.get(service.getComponent());
8953 }
8954 if (r == null) {
8955 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8956 r = mServicesByIntent.get(filter);
8957 }
8958
8959 if (r == null) {
8960 try {
8961 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008962 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008963 service, resolvedType, 0);
8964 ServiceInfo sInfo =
8965 rInfo != null ? rInfo.serviceInfo : null;
8966 if (sInfo == null) {
8967 return null;
8968 }
8969
8970 ComponentName name = new ComponentName(
8971 sInfo.applicationInfo.packageName, sInfo.name);
8972 r = mServices.get(name);
8973 } catch (RemoteException ex) {
8974 // pm is in same process, this will never happen.
8975 }
8976 }
8977 if (r != null) {
8978 int callingPid = Binder.getCallingPid();
8979 int callingUid = Binder.getCallingUid();
8980 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008981 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008982 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008983 if (!r.exported) {
8984 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
8985 + " from pid=" + callingPid
8986 + ", uid=" + callingUid
8987 + " that is not exported from uid " + r.appInfo.uid);
8988 return new ServiceLookupResult(null, "not exported from uid "
8989 + r.appInfo.uid);
8990 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008991 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008992 + " from pid=" + callingPid
8993 + ", uid=" + callingUid
8994 + " requires " + r.permission);
8995 return new ServiceLookupResult(null, r.permission);
8996 }
8997 return new ServiceLookupResult(r, null);
8998 }
8999 return null;
9000 }
9001
9002 private class ServiceRestarter implements Runnable {
9003 private ServiceRecord mService;
9004
9005 void setService(ServiceRecord service) {
9006 mService = service;
9007 }
9008
9009 public void run() {
9010 synchronized(ActivityManagerService.this) {
9011 performServiceRestartLocked(mService);
9012 }
9013 }
9014 }
9015
9016 private ServiceLookupResult retrieveServiceLocked(Intent service,
9017 String resolvedType, int callingPid, int callingUid) {
9018 ServiceRecord r = null;
9019 if (service.getComponent() != null) {
9020 r = mServices.get(service.getComponent());
9021 }
9022 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9023 r = mServicesByIntent.get(filter);
9024 if (r == null) {
9025 try {
9026 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009027 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009028 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009029 ServiceInfo sInfo =
9030 rInfo != null ? rInfo.serviceInfo : null;
9031 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009032 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009033 ": not found");
9034 return null;
9035 }
9036
9037 ComponentName name = new ComponentName(
9038 sInfo.applicationInfo.packageName, sInfo.name);
9039 r = mServices.get(name);
9040 if (r == null) {
9041 filter = new Intent.FilterComparison(service.cloneFilter());
9042 ServiceRestarter res = new ServiceRestarter();
9043 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9044 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9045 synchronized (stats) {
9046 ss = stats.getServiceStatsLocked(
9047 sInfo.applicationInfo.uid, sInfo.packageName,
9048 sInfo.name);
9049 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009050 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009051 res.setService(r);
9052 mServices.put(name, r);
9053 mServicesByIntent.put(filter, r);
9054
9055 // Make sure this component isn't in the pending list.
9056 int N = mPendingServices.size();
9057 for (int i=0; i<N; i++) {
9058 ServiceRecord pr = mPendingServices.get(i);
9059 if (pr.name.equals(name)) {
9060 mPendingServices.remove(i);
9061 i--;
9062 N--;
9063 }
9064 }
9065 }
9066 } catch (RemoteException ex) {
9067 // pm is in same process, this will never happen.
9068 }
9069 }
9070 if (r != null) {
9071 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009072 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009073 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009074 if (!r.exported) {
9075 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9076 + " from pid=" + callingPid
9077 + ", uid=" + callingUid
9078 + " that is not exported from uid " + r.appInfo.uid);
9079 return new ServiceLookupResult(null, "not exported from uid "
9080 + r.appInfo.uid);
9081 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009082 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009083 + " from pid=" + callingPid
9084 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009085 + " requires " + r.permission);
9086 return new ServiceLookupResult(null, r.permission);
9087 }
9088 return new ServiceLookupResult(r, null);
9089 }
9090 return null;
9091 }
9092
Dianne Hackborn287952c2010-09-22 22:34:31 -07009093 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9094 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9095 + why + " of " + r + " in app " + r.app);
9096 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9097 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009098 long now = SystemClock.uptimeMillis();
9099 if (r.executeNesting == 0 && r.app != null) {
9100 if (r.app.executingServices.size() == 0) {
9101 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9102 msg.obj = r.app;
9103 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9104 }
9105 r.app.executingServices.add(r);
9106 }
9107 r.executeNesting++;
9108 r.executingStart = now;
9109 }
9110
9111 private final void sendServiceArgsLocked(ServiceRecord r,
9112 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009113 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009114 if (N == 0) {
9115 return;
9116 }
9117
Dianne Hackborn39792d22010-08-19 18:01:52 -07009118 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009119 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009120 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009121 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9122 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009123 if (si.intent == null && N > 1) {
9124 // If somehow we got a dummy null intent in the middle,
9125 // then skip it. DO NOT skip a null intent when it is
9126 // the only one in the list -- this is to support the
9127 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009128 continue;
9129 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009130 si.deliveredTime = SystemClock.uptimeMillis();
9131 r.deliveredStarts.add(si);
9132 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009133 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009134 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009135 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009136 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009137 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009138 if (!oomAdjusted) {
9139 oomAdjusted = true;
9140 updateOomAdjLocked(r.app);
9141 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009142 int flags = 0;
9143 if (si.deliveryCount > 0) {
9144 flags |= Service.START_FLAG_RETRY;
9145 }
9146 if (si.doneExecutingCount > 0) {
9147 flags |= Service.START_FLAG_REDELIVERY;
9148 }
9149 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009150 } catch (RemoteException e) {
9151 // Remote process gone... we'll let the normal cleanup take
9152 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009153 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009154 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009155 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009156 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009157 break;
9158 }
9159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009160 }
9161
9162 private final boolean requestServiceBindingLocked(ServiceRecord r,
9163 IntentBindRecord i, boolean rebind) {
9164 if (r.app == null || r.app.thread == null) {
9165 // If service is not currently running, can't yet bind.
9166 return false;
9167 }
9168 if ((!i.requested || rebind) && i.apps.size() > 0) {
9169 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009170 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009171 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9172 if (!rebind) {
9173 i.requested = true;
9174 }
9175 i.hasBound = true;
9176 i.doRebind = false;
9177 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009178 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 return false;
9180 }
9181 }
9182 return true;
9183 }
9184
9185 private final void requestServiceBindingsLocked(ServiceRecord r) {
9186 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9187 while (bindings.hasNext()) {
9188 IntentBindRecord i = bindings.next();
9189 if (!requestServiceBindingLocked(r, i, false)) {
9190 break;
9191 }
9192 }
9193 }
9194
9195 private final void realStartServiceLocked(ServiceRecord r,
9196 ProcessRecord app) throws RemoteException {
9197 if (app.thread == null) {
9198 throw new RemoteException();
9199 }
9200
9201 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009202 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009203
9204 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009205 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009206 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009207
9208 boolean created = false;
9209 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009210 mStringBuilder.setLength(0);
9211 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009212 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009213 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009214 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009215 synchronized (r.stats.getBatteryStats()) {
9216 r.stats.startLaunchedLocked();
9217 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009218 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009219 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009220 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 created = true;
9222 } finally {
9223 if (!created) {
9224 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009225 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 }
9227 }
9228
9229 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009230
9231 // If the service is in the started state, and there are no
9232 // pending arguments, then fake up one so its onStartCommand() will
9233 // be called.
9234 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9235 r.lastStartId++;
9236 if (r.lastStartId < 1) {
9237 r.lastStartId = 1;
9238 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009239 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009240 }
9241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009242 sendServiceArgsLocked(r, true);
9243 }
9244
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009245 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9246 boolean allowCancel) {
9247 boolean canceled = false;
9248
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009249 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009250 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009251 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009252
Dianne Hackborn070783f2010-12-29 16:46:28 -08009253 if ((r.serviceInfo.applicationInfo.flags
9254 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9255 minDuration /= 4;
9256 }
9257
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009258 // Any delivered but not yet finished starts should be put back
9259 // on the pending list.
9260 final int N = r.deliveredStarts.size();
9261 if (N > 0) {
9262 for (int i=N-1; i>=0; i--) {
9263 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009264 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009265 if (si.intent == null) {
9266 // We'll generate this again if needed.
9267 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9268 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9269 r.pendingStarts.add(0, si);
9270 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9271 dur *= 2;
9272 if (minDuration < dur) minDuration = dur;
9273 if (resetTime < dur) resetTime = dur;
9274 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009275 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009276 + r.name);
9277 canceled = true;
9278 }
9279 }
9280 r.deliveredStarts.clear();
9281 }
9282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009283 r.totalRestartCount++;
9284 if (r.restartDelay == 0) {
9285 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009286 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009287 } else {
9288 // If it has been a "reasonably long time" since the service
9289 // was started, then reset our restart duration back to
9290 // the beginning, so we don't infinitely increase the duration
9291 // on a service that just occasionally gets killed (which is
9292 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009293 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009294 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009295 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009296 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009297 if ((r.serviceInfo.applicationInfo.flags
9298 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9299 // Services in peristent processes will restart much more
9300 // quickly, since they are pretty important. (Think SystemUI).
9301 r.restartDelay += minDuration/2;
9302 } else {
9303 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9304 if (r.restartDelay < minDuration) {
9305 r.restartDelay = minDuration;
9306 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009308 }
9309 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009310
9311 r.nextRestartTime = now + r.restartDelay;
9312
9313 // Make sure that we don't end up restarting a bunch of services
9314 // all at the same time.
9315 boolean repeat;
9316 do {
9317 repeat = false;
9318 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9319 ServiceRecord r2 = mRestartingServices.get(i);
9320 if (r2 != r && r.nextRestartTime
9321 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9322 && r.nextRestartTime
9323 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9324 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9325 r.restartDelay = r.nextRestartTime - now;
9326 repeat = true;
9327 break;
9328 }
9329 }
9330 } while (repeat);
9331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009332 if (!mRestartingServices.contains(r)) {
9333 mRestartingServices.add(r);
9334 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009335
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009336 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009338 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009339 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009341 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009342 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009343 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009344 r.shortName, r.restartDelay);
9345
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009346 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009347 }
9348
9349 final void performServiceRestartLocked(ServiceRecord r) {
9350 if (!mRestartingServices.contains(r)) {
9351 return;
9352 }
9353 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9354 }
9355
9356 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9357 if (r.restartDelay == 0) {
9358 return false;
9359 }
9360 r.resetRestartCounter();
9361 mRestartingServices.remove(r);
9362 mHandler.removeCallbacks(r.restarter);
9363 return true;
9364 }
9365
9366 private final boolean bringUpServiceLocked(ServiceRecord r,
9367 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009368 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009369 //r.dump(" ");
9370
Dianne Hackborn36124872009-10-08 16:22:03 -07009371 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009372 sendServiceArgsLocked(r, false);
9373 return true;
9374 }
9375
9376 if (!whileRestarting && r.restartDelay > 0) {
9377 // If waiting for a restart, then do nothing.
9378 return true;
9379 }
9380
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009381 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009382
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009383 // We are now bringing the service up, so no longer in the
9384 // restarting state.
9385 mRestartingServices.remove(r);
9386
Dianne Hackborne7f97212011-02-24 14:40:20 -08009387 // Service is now being launched, its package can't be stopped.
9388 try {
9389 AppGlobals.getPackageManager().setPackageStoppedState(
9390 r.packageName, false);
9391 } catch (RemoteException e) {
9392 }
9393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009394 final String appName = r.processName;
9395 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9396 if (app != null && app.thread != null) {
9397 try {
9398 realStartServiceLocked(r, app);
9399 return true;
9400 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009401 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009402 }
9403
9404 // If a dead object exception was thrown -- fall through to
9405 // restart the application.
9406 }
9407
Dianne Hackborn36124872009-10-08 16:22:03 -07009408 // Not running -- get it started, and enqueue this service record
9409 // to be executed when the app comes up.
9410 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9411 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009412 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009413 + r.appInfo.packageName + "/"
9414 + r.appInfo.uid + " for service "
9415 + r.intent.getIntent() + ": process is bad");
9416 bringDownServiceLocked(r, true);
9417 return false;
9418 }
9419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009420 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009421 mPendingServices.add(r);
9422 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009424 return true;
9425 }
9426
9427 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009428 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009429 //r.dump(" ");
9430
9431 // Does it still need to run?
9432 if (!force && r.startRequested) {
9433 return;
9434 }
9435 if (r.connections.size() > 0) {
9436 if (!force) {
9437 // XXX should probably keep a count of the number of auto-create
9438 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009439 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009440 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009441 ArrayList<ConnectionRecord> cr = it.next();
9442 for (int i=0; i<cr.size(); i++) {
9443 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9444 return;
9445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009446 }
9447 }
9448 }
9449
9450 // Report to all of the connections that the service is no longer
9451 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009452 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009453 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009454 ArrayList<ConnectionRecord> c = it.next();
9455 for (int i=0; i<c.size(); i++) {
9456 try {
9457 c.get(i).conn.connected(r.name, null);
9458 } catch (Exception e) {
9459 Slog.w(TAG, "Failure disconnecting service " + r.name +
9460 " to connection " + c.get(i).conn.asBinder() +
9461 " (in " + c.get(i).binding.client.processName + ")", e);
9462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009463 }
9464 }
9465 }
9466
9467 // Tell the service that it has been unbound.
9468 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9469 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9470 while (it.hasNext()) {
9471 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009472 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009473 + ": hasBound=" + ibr.hasBound);
9474 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9475 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009476 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009477 updateOomAdjLocked(r.app);
9478 ibr.hasBound = false;
9479 r.app.thread.scheduleUnbindService(r,
9480 ibr.intent.getIntent());
9481 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009482 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009483 + r.shortName, e);
9484 serviceDoneExecutingLocked(r, true);
9485 }
9486 }
9487 }
9488 }
9489
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009490 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009491 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009492 System.identityHashCode(r), r.shortName,
9493 (r.app != null) ? r.app.pid : -1);
9494
9495 mServices.remove(r.name);
9496 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009497 r.totalRestartCount = 0;
9498 unscheduleServiceRestartLocked(r);
9499
9500 // Also make sure it is not on the pending list.
9501 int N = mPendingServices.size();
9502 for (int i=0; i<N; i++) {
9503 if (mPendingServices.get(i) == r) {
9504 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009505 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009506 i--;
9507 N--;
9508 }
9509 }
9510
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009511 r.cancelNotification();
9512 r.isForeground = false;
9513 r.foregroundId = 0;
9514 r.foregroundNoti = null;
9515
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009516 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009517 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009518 r.pendingStarts.clear();
9519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009520 if (r.app != null) {
9521 synchronized (r.stats.getBatteryStats()) {
9522 r.stats.stopLaunchedLocked();
9523 }
9524 r.app.services.remove(r);
9525 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009526 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009527 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009528 mStoppingServices.add(r);
9529 updateOomAdjLocked(r.app);
9530 r.app.thread.scheduleStopService(r);
9531 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009532 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009533 + r.shortName, e);
9534 serviceDoneExecutingLocked(r, true);
9535 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009536 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009537 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009538 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009539 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009540 }
9541 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009542 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009543 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009544 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -08009545
9546 if (r.bindings.size() > 0) {
9547 r.bindings.clear();
9548 }
9549
9550 if (r.restarter instanceof ServiceRestarter) {
9551 ((ServiceRestarter)r.restarter).setService(null);
9552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009553 }
9554
9555 ComponentName startServiceLocked(IApplicationThread caller,
9556 Intent service, String resolvedType,
9557 int callingPid, int callingUid) {
9558 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009559 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009560 + " type=" + resolvedType + " args=" + service.getExtras());
9561
9562 if (caller != null) {
9563 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9564 if (callerApp == null) {
9565 throw new SecurityException(
9566 "Unable to find app for caller " + caller
9567 + " (pid=" + Binder.getCallingPid()
9568 + ") when starting service " + service);
9569 }
9570 }
9571
9572 ServiceLookupResult res =
9573 retrieveServiceLocked(service, resolvedType,
9574 callingPid, callingUid);
9575 if (res == null) {
9576 return null;
9577 }
9578 if (res.record == null) {
9579 return new ComponentName("!", res.permission != null
9580 ? res.permission : "private to package");
9581 }
9582 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009583 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9584 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009585 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009586 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009587 }
9588 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009589 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009590 r.lastStartId++;
9591 if (r.lastStartId < 1) {
9592 r.lastStartId = 1;
9593 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009594 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9595 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009596 r.lastActivity = SystemClock.uptimeMillis();
9597 synchronized (r.stats.getBatteryStats()) {
9598 r.stats.startRunningLocked();
9599 }
9600 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9601 return new ComponentName("!", "Service process is bad");
9602 }
9603 return r.name;
9604 }
9605 }
9606
9607 public ComponentName startService(IApplicationThread caller, Intent service,
9608 String resolvedType) {
9609 // Refuse possible leaked file descriptors
9610 if (service != null && service.hasFileDescriptors() == true) {
9611 throw new IllegalArgumentException("File descriptors passed in Intent");
9612 }
9613
9614 synchronized(this) {
9615 final int callingPid = Binder.getCallingPid();
9616 final int callingUid = Binder.getCallingUid();
9617 final long origId = Binder.clearCallingIdentity();
9618 ComponentName res = startServiceLocked(caller, service,
9619 resolvedType, callingPid, callingUid);
9620 Binder.restoreCallingIdentity(origId);
9621 return res;
9622 }
9623 }
9624
9625 ComponentName startServiceInPackage(int uid,
9626 Intent service, String resolvedType) {
9627 synchronized(this) {
9628 final long origId = Binder.clearCallingIdentity();
9629 ComponentName res = startServiceLocked(null, service,
9630 resolvedType, -1, uid);
9631 Binder.restoreCallingIdentity(origId);
9632 return res;
9633 }
9634 }
9635
9636 public int stopService(IApplicationThread caller, Intent service,
9637 String resolvedType) {
9638 // Refuse possible leaked file descriptors
9639 if (service != null && service.hasFileDescriptors() == true) {
9640 throw new IllegalArgumentException("File descriptors passed in Intent");
9641 }
9642
9643 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009644 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009645 + " type=" + resolvedType);
9646
9647 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9648 if (caller != null && callerApp == null) {
9649 throw new SecurityException(
9650 "Unable to find app for caller " + caller
9651 + " (pid=" + Binder.getCallingPid()
9652 + ") when stopping service " + service);
9653 }
9654
9655 // If this service is active, make sure it is stopped.
9656 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9657 if (r != null) {
9658 if (r.record != null) {
9659 synchronized (r.record.stats.getBatteryStats()) {
9660 r.record.stats.stopRunningLocked();
9661 }
9662 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009663 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009664 final long origId = Binder.clearCallingIdentity();
9665 bringDownServiceLocked(r.record, false);
9666 Binder.restoreCallingIdentity(origId);
9667 return 1;
9668 }
9669 return -1;
9670 }
9671 }
9672
9673 return 0;
9674 }
9675
9676 public IBinder peekService(Intent service, String resolvedType) {
9677 // Refuse possible leaked file descriptors
9678 if (service != null && service.hasFileDescriptors() == true) {
9679 throw new IllegalArgumentException("File descriptors passed in Intent");
9680 }
9681
9682 IBinder ret = null;
9683
9684 synchronized(this) {
9685 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9686
9687 if (r != null) {
9688 // r.record is null if findServiceLocked() failed the caller permission check
9689 if (r.record == null) {
9690 throw new SecurityException(
9691 "Permission Denial: Accessing service " + r.record.name
9692 + " from pid=" + Binder.getCallingPid()
9693 + ", uid=" + Binder.getCallingUid()
9694 + " requires " + r.permission);
9695 }
9696 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9697 if (ib != null) {
9698 ret = ib.binder;
9699 }
9700 }
9701 }
9702
9703 return ret;
9704 }
9705
9706 public boolean stopServiceToken(ComponentName className, IBinder token,
9707 int startId) {
9708 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009709 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009710 + " " + token + " startId=" + startId);
9711 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009712 if (r != null) {
9713 if (startId >= 0) {
9714 // Asked to only stop if done with all work. Note that
9715 // to avoid leaks, we will take this as dropping all
9716 // start items up to and including this one.
9717 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9718 if (si != null) {
9719 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009720 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9721 cur.removeUriPermissionsLocked();
9722 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009723 break;
9724 }
9725 }
9726 }
9727
9728 if (r.lastStartId != startId) {
9729 return false;
9730 }
9731
9732 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009733 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009734 + " is last, but have " + r.deliveredStarts.size()
9735 + " remaining args");
9736 }
9737 }
9738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009739 synchronized (r.stats.getBatteryStats()) {
9740 r.stats.stopRunningLocked();
9741 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009742 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009743 }
9744 final long origId = Binder.clearCallingIdentity();
9745 bringDownServiceLocked(r, false);
9746 Binder.restoreCallingIdentity(origId);
9747 return true;
9748 }
9749 }
9750 return false;
9751 }
9752
9753 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009754 int id, Notification notification, boolean removeNotification) {
9755 final long origId = Binder.clearCallingIdentity();
9756 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 synchronized(this) {
9758 ServiceRecord r = findServiceLocked(className, token);
9759 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009760 if (id != 0) {
9761 if (notification == null) {
9762 throw new IllegalArgumentException("null notification");
9763 }
9764 if (r.foregroundId != id) {
9765 r.cancelNotification();
9766 r.foregroundId = id;
9767 }
9768 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9769 r.foregroundNoti = notification;
9770 r.isForeground = true;
9771 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009772 if (r.app != null) {
9773 updateServiceForegroundLocked(r.app, true);
9774 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009775 } else {
9776 if (r.isForeground) {
9777 r.isForeground = false;
9778 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009779 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009780 updateServiceForegroundLocked(r.app, true);
9781 }
9782 }
9783 if (removeNotification) {
9784 r.cancelNotification();
9785 r.foregroundId = 0;
9786 r.foregroundNoti = null;
9787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788 }
9789 }
9790 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009791 } finally {
9792 Binder.restoreCallingIdentity(origId);
9793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794 }
9795
9796 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9797 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009798 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009799 if (sr.isForeground) {
9800 anyForeground = true;
9801 break;
9802 }
9803 }
9804 if (anyForeground != proc.foregroundServices) {
9805 proc.foregroundServices = anyForeground;
9806 if (oomAdj) {
9807 updateOomAdjLocked();
9808 }
9809 }
9810 }
9811
9812 public int bindService(IApplicationThread caller, IBinder token,
9813 Intent service, String resolvedType,
9814 IServiceConnection connection, int flags) {
9815 // Refuse possible leaked file descriptors
9816 if (service != null && service.hasFileDescriptors() == true) {
9817 throw new IllegalArgumentException("File descriptors passed in Intent");
9818 }
9819
9820 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009821 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009822 + " type=" + resolvedType + " conn=" + connection.asBinder()
9823 + " flags=0x" + Integer.toHexString(flags));
9824 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9825 if (callerApp == null) {
9826 throw new SecurityException(
9827 "Unable to find app for caller " + caller
9828 + " (pid=" + Binder.getCallingPid()
9829 + ") when binding service " + service);
9830 }
9831
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009832 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009834 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009835 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009836 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009837 return 0;
9838 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009839 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009840 }
9841
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009842 int clientLabel = 0;
9843 PendingIntent clientIntent = null;
9844
9845 if (callerApp.info.uid == Process.SYSTEM_UID) {
9846 // Hacky kind of thing -- allow system stuff to tell us
9847 // what they are, so we can report this elsewhere for
9848 // others to know why certain services are running.
9849 try {
9850 clientIntent = (PendingIntent)service.getParcelableExtra(
9851 Intent.EXTRA_CLIENT_INTENT);
9852 } catch (RuntimeException e) {
9853 }
9854 if (clientIntent != null) {
9855 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9856 if (clientLabel != 0) {
9857 // There are no useful extras in the intent, trash them.
9858 // System code calling with this stuff just needs to know
9859 // this will happen.
9860 service = service.cloneFilter();
9861 }
9862 }
9863 }
9864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865 ServiceLookupResult res =
9866 retrieveServiceLocked(service, resolvedType,
9867 Binder.getCallingPid(), Binder.getCallingUid());
9868 if (res == null) {
9869 return 0;
9870 }
9871 if (res.record == null) {
9872 return -1;
9873 }
9874 ServiceRecord s = res.record;
9875
9876 final long origId = Binder.clearCallingIdentity();
9877
9878 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009879 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009880 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009881 }
9882
9883 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9884 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009885 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009886
9887 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009888 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9889 if (clist == null) {
9890 clist = new ArrayList<ConnectionRecord>();
9891 s.connections.put(binder, clist);
9892 }
9893 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009894 b.connections.add(c);
9895 if (activity != null) {
9896 if (activity.connections == null) {
9897 activity.connections = new HashSet<ConnectionRecord>();
9898 }
9899 activity.connections.add(c);
9900 }
9901 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009902 clist = mServiceConnections.get(binder);
9903 if (clist == null) {
9904 clist = new ArrayList<ConnectionRecord>();
9905 mServiceConnections.put(binder, clist);
9906 }
9907 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009908
9909 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9910 s.lastActivity = SystemClock.uptimeMillis();
9911 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9912 return 0;
9913 }
9914 }
9915
9916 if (s.app != null) {
9917 // This could have made the service more important.
9918 updateOomAdjLocked(s.app);
9919 }
9920
Joe Onorato8a9b2202010-02-26 18:56:32 -08009921 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 + ": received=" + b.intent.received
9923 + " apps=" + b.intent.apps.size()
9924 + " doRebind=" + b.intent.doRebind);
9925
9926 if (s.app != null && b.intent.received) {
9927 // Service is already running, so we can immediately
9928 // publish the connection.
9929 try {
9930 c.conn.connected(s.name, b.intent.binder);
9931 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009932 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009933 + " to connection " + c.conn.asBinder()
9934 + " (in " + c.binding.client.processName + ")", e);
9935 }
9936
9937 // If this is the first app connected back to this binding,
9938 // and the service had previously asked to be told when
9939 // rebound, then do so.
9940 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9941 requestServiceBindingLocked(s, b.intent, true);
9942 }
9943 } else if (!b.intent.requested) {
9944 requestServiceBindingLocked(s, b.intent, false);
9945 }
9946
9947 Binder.restoreCallingIdentity(origId);
9948 }
9949
9950 return 1;
9951 }
9952
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009953 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009954 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009955 IBinder binder = c.conn.asBinder();
9956 AppBindRecord b = c.binding;
9957 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009958 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9959 if (clist != null) {
9960 clist.remove(c);
9961 if (clist.size() == 0) {
9962 s.connections.remove(binder);
9963 }
9964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009965 b.connections.remove(c);
9966 if (c.activity != null && c.activity != skipAct) {
9967 if (c.activity.connections != null) {
9968 c.activity.connections.remove(c);
9969 }
9970 }
9971 if (b.client != skipApp) {
9972 b.client.connections.remove(c);
9973 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009974 clist = mServiceConnections.get(binder);
9975 if (clist != null) {
9976 clist.remove(c);
9977 if (clist.size() == 0) {
9978 mServiceConnections.remove(binder);
9979 }
9980 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009981
9982 if (b.connections.size() == 0) {
9983 b.intent.apps.remove(b.client);
9984 }
9985
Joe Onorato8a9b2202010-02-26 18:56:32 -08009986 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009987 + ": shouldUnbind=" + b.intent.hasBound);
9988 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9989 && b.intent.hasBound) {
9990 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009991 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009992 updateOomAdjLocked(s.app);
9993 b.intent.hasBound = false;
9994 // Assume the client doesn't want to know about a rebind;
9995 // we will deal with that later if it asks for one.
9996 b.intent.doRebind = false;
9997 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9998 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009999 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000 serviceDoneExecutingLocked(s, true);
10001 }
10002 }
10003
10004 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10005 bringDownServiceLocked(s, false);
10006 }
10007 }
10008
10009 public boolean unbindService(IServiceConnection connection) {
10010 synchronized (this) {
10011 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010012 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010013 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10014 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010015 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010016 + connection.asBinder());
10017 return false;
10018 }
10019
10020 final long origId = Binder.clearCallingIdentity();
10021
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010022 while (clist.size() > 0) {
10023 ConnectionRecord r = clist.get(0);
10024 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010025
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010026 if (r.binding.service.app != null) {
10027 // This could have made the service less important.
10028 updateOomAdjLocked(r.binding.service.app);
10029 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010030 }
10031
10032 Binder.restoreCallingIdentity(origId);
10033 }
10034
10035 return true;
10036 }
10037
10038 public void publishService(IBinder token, Intent intent, IBinder service) {
10039 // Refuse possible leaked file descriptors
10040 if (intent != null && intent.hasFileDescriptors() == true) {
10041 throw new IllegalArgumentException("File descriptors passed in Intent");
10042 }
10043
10044 synchronized(this) {
10045 if (!(token instanceof ServiceRecord)) {
10046 throw new IllegalArgumentException("Invalid service token");
10047 }
10048 ServiceRecord r = (ServiceRecord)token;
10049
10050 final long origId = Binder.clearCallingIdentity();
10051
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010052 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010053 + " " + intent + ": " + service);
10054 if (r != null) {
10055 Intent.FilterComparison filter
10056 = new Intent.FilterComparison(intent);
10057 IntentBindRecord b = r.bindings.get(filter);
10058 if (b != null && !b.received) {
10059 b.binder = service;
10060 b.requested = true;
10061 b.received = true;
10062 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010063 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010064 = r.connections.values().iterator();
10065 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010066 ArrayList<ConnectionRecord> clist = it.next();
10067 for (int i=0; i<clist.size(); i++) {
10068 ConnectionRecord c = clist.get(i);
10069 if (!filter.equals(c.binding.intent.intent)) {
10070 if (DEBUG_SERVICE) Slog.v(
10071 TAG, "Not publishing to: " + c);
10072 if (DEBUG_SERVICE) Slog.v(
10073 TAG, "Bound intent: " + c.binding.intent.intent);
10074 if (DEBUG_SERVICE) Slog.v(
10075 TAG, "Published intent: " + intent);
10076 continue;
10077 }
10078 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10079 try {
10080 c.conn.connected(r.name, service);
10081 } catch (Exception e) {
10082 Slog.w(TAG, "Failure sending service " + r.name +
10083 " to connection " + c.conn.asBinder() +
10084 " (in " + c.binding.client.processName + ")", e);
10085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010086 }
10087 }
10088 }
10089 }
10090
10091 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10092
10093 Binder.restoreCallingIdentity(origId);
10094 }
10095 }
10096 }
10097
10098 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10099 // Refuse possible leaked file descriptors
10100 if (intent != null && intent.hasFileDescriptors() == true) {
10101 throw new IllegalArgumentException("File descriptors passed in Intent");
10102 }
10103
10104 synchronized(this) {
10105 if (!(token instanceof ServiceRecord)) {
10106 throw new IllegalArgumentException("Invalid service token");
10107 }
10108 ServiceRecord r = (ServiceRecord)token;
10109
10110 final long origId = Binder.clearCallingIdentity();
10111
10112 if (r != null) {
10113 Intent.FilterComparison filter
10114 = new Intent.FilterComparison(intent);
10115 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010116 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010117 + " at " + b + ": apps="
10118 + (b != null ? b.apps.size() : 0));
10119 if (b != null) {
10120 if (b.apps.size() > 0) {
10121 // Applications have already bound since the last
10122 // unbind, so just rebind right here.
10123 requestServiceBindingLocked(r, b, true);
10124 } else {
10125 // Note to tell the service the next time there is
10126 // a new client.
10127 b.doRebind = true;
10128 }
10129 }
10130
10131 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10132
10133 Binder.restoreCallingIdentity(origId);
10134 }
10135 }
10136 }
10137
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010138 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010139 synchronized(this) {
10140 if (!(token instanceof ServiceRecord)) {
10141 throw new IllegalArgumentException("Invalid service token");
10142 }
10143 ServiceRecord r = (ServiceRecord)token;
10144 boolean inStopping = mStoppingServices.contains(token);
10145 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010146 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010147 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010148 + " with incorrect token: given " + token
10149 + ", expected " + r);
10150 return;
10151 }
10152
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010153 if (type == 1) {
10154 // This is a call from a service start... take care of
10155 // book-keeping.
10156 r.callStart = true;
10157 switch (res) {
10158 case Service.START_STICKY_COMPATIBILITY:
10159 case Service.START_STICKY: {
10160 // We are done with the associated start arguments.
10161 r.findDeliveredStart(startId, true);
10162 // Don't stop if killed.
10163 r.stopIfKilled = false;
10164 break;
10165 }
10166 case Service.START_NOT_STICKY: {
10167 // We are done with the associated start arguments.
10168 r.findDeliveredStart(startId, true);
10169 if (r.lastStartId == startId) {
10170 // There is no more work, and this service
10171 // doesn't want to hang around if killed.
10172 r.stopIfKilled = true;
10173 }
10174 break;
10175 }
10176 case Service.START_REDELIVER_INTENT: {
10177 // We'll keep this item until they explicitly
10178 // call stop for it, but keep track of the fact
10179 // that it was delivered.
10180 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10181 if (si != null) {
10182 si.deliveryCount = 0;
10183 si.doneExecutingCount++;
10184 // Don't stop if killed.
10185 r.stopIfKilled = true;
10186 }
10187 break;
10188 }
10189 default:
10190 throw new IllegalArgumentException(
10191 "Unknown service start result: " + res);
10192 }
10193 if (res == Service.START_STICKY_COMPATIBILITY) {
10194 r.callStart = false;
10195 }
10196 }
10197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010198 final long origId = Binder.clearCallingIdentity();
10199 serviceDoneExecutingLocked(r, inStopping);
10200 Binder.restoreCallingIdentity(origId);
10201 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010202 Slog.w(TAG, "Done executing unknown service from pid "
10203 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010204 }
10205 }
10206 }
10207
10208 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010209 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10210 + ": nesting=" + r.executeNesting
10211 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010212 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010213 r.executeNesting--;
10214 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010215 if (DEBUG_SERVICE) Slog.v(TAG,
10216 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010217 r.app.executingServices.remove(r);
10218 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010219 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10220 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010221 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10222 }
10223 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010224 if (DEBUG_SERVICE) Slog.v(TAG,
10225 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010226 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010227 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010228 }
10229 updateOomAdjLocked(r.app);
10230 }
10231 }
10232
10233 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010234 String anrMessage = null;
10235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236 synchronized(this) {
10237 if (proc.executingServices.size() == 0 || proc.thread == null) {
10238 return;
10239 }
10240 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10241 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10242 ServiceRecord timeout = null;
10243 long nextTime = 0;
10244 while (it.hasNext()) {
10245 ServiceRecord sr = it.next();
10246 if (sr.executingStart < maxTime) {
10247 timeout = sr;
10248 break;
10249 }
10250 if (sr.executingStart > nextTime) {
10251 nextTime = sr.executingStart;
10252 }
10253 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010254 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010255 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010256 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010257 } else {
10258 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10259 msg.obj = proc;
10260 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10261 }
10262 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010263
10264 if (anrMessage != null) {
10265 appNotResponding(proc, null, null, anrMessage);
10266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010267 }
10268
10269 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010270 // BACKUP AND RESTORE
10271 // =========================================================
10272
10273 // Cause the target app to be launched if necessary and its backup agent
10274 // instantiated. The backup agent will invoke backupAgentCreated() on the
10275 // activity manager to announce its creation.
10276 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010277 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010278 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10279
10280 synchronized(this) {
10281 // !!! TODO: currently no check here that we're already bound
10282 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10283 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10284 synchronized (stats) {
10285 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10286 }
10287
Dianne Hackborne7f97212011-02-24 14:40:20 -080010288 // Backup agent is now in use, its package can't be stopped.
10289 try {
10290 AppGlobals.getPackageManager().setPackageStoppedState(
10291 app.packageName, false);
10292 } catch (RemoteException e) {
10293 }
10294
Christopher Tate181fafa2009-05-14 11:12:14 -070010295 BackupRecord r = new BackupRecord(ss, app, backupMode);
10296 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10297 // startProcessLocked() returns existing proc's record if it's already running
10298 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010299 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010300 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010301 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010302 return false;
10303 }
10304
10305 r.app = proc;
10306 mBackupTarget = r;
10307 mBackupAppName = app.packageName;
10308
Christopher Tate6fa95972009-06-05 18:43:55 -070010309 // Try not to kill the process during backup
10310 updateOomAdjLocked(proc);
10311
Christopher Tate181fafa2009-05-14 11:12:14 -070010312 // If the process is already attached, schedule the creation of the backup agent now.
10313 // If it is not yet live, this will be done when it attaches to the framework.
10314 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010315 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010316 try {
10317 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10318 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010319 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010320 }
10321 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010322 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010323 }
10324 // Invariants: at this point, the target app process exists and the application
10325 // is either already running or in the process of coming up. mBackupTarget and
10326 // mBackupAppName describe the app, so that when it binds back to the AM we
10327 // know that it's scheduled for a backup-agent operation.
10328 }
10329
10330 return true;
10331 }
10332
10333 // A backup agent has just come up
10334 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010335 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010336 + " = " + agent);
10337
10338 synchronized(this) {
10339 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010340 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010341 return;
10342 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010343 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010344
Dianne Hackborn06740692010-09-22 22:46:21 -070010345 long oldIdent = Binder.clearCallingIdentity();
10346 try {
10347 IBackupManager bm = IBackupManager.Stub.asInterface(
10348 ServiceManager.getService(Context.BACKUP_SERVICE));
10349 bm.agentConnected(agentPackageName, agent);
10350 } catch (RemoteException e) {
10351 // can't happen; the backup manager service is local
10352 } catch (Exception e) {
10353 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10354 e.printStackTrace();
10355 } finally {
10356 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010357 }
10358 }
10359
10360 // done with this agent
10361 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010362 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010363 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010364 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010365 return;
10366 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010367
10368 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010369 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010370 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010371 return;
10372 }
10373
Christopher Tate181fafa2009-05-14 11:12:14 -070010374 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010375 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010376 return;
10377 }
10378
Christopher Tate6fa95972009-06-05 18:43:55 -070010379 ProcessRecord proc = mBackupTarget.app;
10380 mBackupTarget = null;
10381 mBackupAppName = null;
10382
10383 // Not backing this app up any more; reset its OOM adjustment
10384 updateOomAdjLocked(proc);
10385
Christopher Tatec7b31e32009-06-10 15:49:30 -070010386 // If the app crashed during backup, 'thread' will be null here
10387 if (proc.thread != null) {
10388 try {
10389 proc.thread.scheduleDestroyBackupAgent(appInfo);
10390 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010391 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010392 e.printStackTrace();
10393 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010394 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010395 }
10396 }
10397 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010398 // BROADCASTS
10399 // =========================================================
10400
Josh Bartel7f208742010-02-25 11:01:44 -060010401 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010402 List cur) {
10403 final ContentResolver resolver = mContext.getContentResolver();
10404 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10405 if (list == null) {
10406 return cur;
10407 }
10408 int N = list.size();
10409 for (int i=0; i<N; i++) {
10410 Intent intent = list.get(i);
10411 if (filter.match(resolver, intent, true, TAG) >= 0) {
10412 if (cur == null) {
10413 cur = new ArrayList<Intent>();
10414 }
10415 cur.add(intent);
10416 }
10417 }
10418 return cur;
10419 }
10420
10421 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010422 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 + mBroadcastsScheduled);
10424
10425 if (mBroadcastsScheduled) {
10426 return;
10427 }
10428 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10429 mBroadcastsScheduled = true;
10430 }
10431
10432 public Intent registerReceiver(IApplicationThread caller,
10433 IIntentReceiver receiver, IntentFilter filter, String permission) {
10434 synchronized(this) {
10435 ProcessRecord callerApp = null;
10436 if (caller != null) {
10437 callerApp = getRecordForAppLocked(caller);
10438 if (callerApp == null) {
10439 throw new SecurityException(
10440 "Unable to find app for caller " + caller
10441 + " (pid=" + Binder.getCallingPid()
10442 + ") when registering receiver " + receiver);
10443 }
10444 }
10445
10446 List allSticky = null;
10447
10448 // Look for any matching sticky broadcasts...
10449 Iterator actions = filter.actionsIterator();
10450 if (actions != null) {
10451 while (actions.hasNext()) {
10452 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010453 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010454 }
10455 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010456 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010457 }
10458
10459 // The first sticky in the list is returned directly back to
10460 // the client.
10461 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10462
Joe Onorato8a9b2202010-02-26 18:56:32 -080010463 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010464 + ": " + sticky);
10465
10466 if (receiver == null) {
10467 return sticky;
10468 }
10469
10470 ReceiverList rl
10471 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10472 if (rl == null) {
10473 rl = new ReceiverList(this, callerApp,
10474 Binder.getCallingPid(),
10475 Binder.getCallingUid(), receiver);
10476 if (rl.app != null) {
10477 rl.app.receivers.add(rl);
10478 } else {
10479 try {
10480 receiver.asBinder().linkToDeath(rl, 0);
10481 } catch (RemoteException e) {
10482 return sticky;
10483 }
10484 rl.linkedToDeath = true;
10485 }
10486 mRegisteredReceivers.put(receiver.asBinder(), rl);
10487 }
10488 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10489 rl.add(bf);
10490 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010491 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010492 }
10493 mReceiverResolver.addFilter(bf);
10494
10495 // Enqueue broadcasts for all existing stickies that match
10496 // this filter.
10497 if (allSticky != null) {
10498 ArrayList receivers = new ArrayList();
10499 receivers.add(bf);
10500
10501 int N = allSticky.size();
10502 for (int i=0; i<N; i++) {
10503 Intent intent = (Intent)allSticky.get(i);
10504 BroadcastRecord r = new BroadcastRecord(intent, null,
10505 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010506 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010507 if (mParallelBroadcasts.size() == 0) {
10508 scheduleBroadcastsLocked();
10509 }
10510 mParallelBroadcasts.add(r);
10511 }
10512 }
10513
10514 return sticky;
10515 }
10516 }
10517
10518 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010519 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010520
10521 boolean doNext = false;
10522
10523 synchronized(this) {
10524 ReceiverList rl
10525 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10526 if (rl != null) {
10527 if (rl.curBroadcast != null) {
10528 BroadcastRecord r = rl.curBroadcast;
10529 doNext = finishReceiverLocked(
10530 receiver.asBinder(), r.resultCode, r.resultData,
10531 r.resultExtras, r.resultAbort, true);
10532 }
10533
10534 if (rl.app != null) {
10535 rl.app.receivers.remove(rl);
10536 }
10537 removeReceiverLocked(rl);
10538 if (rl.linkedToDeath) {
10539 rl.linkedToDeath = false;
10540 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10541 }
10542 }
10543 }
10544
10545 if (!doNext) {
10546 return;
10547 }
10548
10549 final long origId = Binder.clearCallingIdentity();
10550 processNextBroadcast(false);
10551 trimApplications();
10552 Binder.restoreCallingIdentity(origId);
10553 }
10554
10555 void removeReceiverLocked(ReceiverList rl) {
10556 mRegisteredReceivers.remove(rl.receiver.asBinder());
10557 int N = rl.size();
10558 for (int i=0; i<N; i++) {
10559 mReceiverResolver.removeFilter(rl.get(i));
10560 }
10561 }
10562
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010563 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10564 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10565 ProcessRecord r = mLruProcesses.get(i);
10566 if (r.thread != null) {
10567 try {
10568 r.thread.dispatchPackageBroadcast(cmd, packages);
10569 } catch (RemoteException ex) {
10570 }
10571 }
10572 }
10573 }
10574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010575 private final int broadcastIntentLocked(ProcessRecord callerApp,
10576 String callerPackage, Intent intent, String resolvedType,
10577 IIntentReceiver resultTo, int resultCode, String resultData,
10578 Bundle map, String requiredPermission,
10579 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10580 intent = new Intent(intent);
10581
Dianne Hackborne7f97212011-02-24 14:40:20 -080010582 // By default broadcasts do not go to stopped apps.
10583 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
10584
Joe Onorato8a9b2202010-02-26 18:56:32 -080010585 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010586 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10587 + " ordered=" + ordered);
10588 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010589 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010590 }
10591
10592 // Handle special intents: if this broadcast is from the package
10593 // manager about a package being removed, we need to remove all of
10594 // its activities from the history stack.
10595 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10596 intent.getAction());
10597 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10598 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010599 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010600 || uidRemoved) {
10601 if (checkComponentPermission(
10602 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010603 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010604 == PackageManager.PERMISSION_GRANTED) {
10605 if (uidRemoved) {
10606 final Bundle intentExtras = intent.getExtras();
10607 final int uid = intentExtras != null
10608 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10609 if (uid >= 0) {
10610 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10611 synchronized (bs) {
10612 bs.removeUidStatsLocked(uid);
10613 }
10614 }
10615 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010616 // If resources are unvailble just force stop all
10617 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010618 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010619 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10620 if (list != null && (list.length > 0)) {
10621 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010622 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010623 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010624 sendPackageBroadcastLocked(
10625 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010626 }
10627 } else {
10628 Uri data = intent.getData();
10629 String ssp;
10630 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10631 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10632 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010633 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010634 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010635 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10636 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10637 new String[] {ssp});
10638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010639 }
10640 }
10641 }
10642 } else {
10643 String msg = "Permission Denial: " + intent.getAction()
10644 + " broadcast from " + callerPackage + " (pid=" + callingPid
10645 + ", uid=" + callingUid + ")"
10646 + " requires "
10647 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010648 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010649 throw new SecurityException(msg);
10650 }
10651 }
10652
10653 /*
10654 * If this is the time zone changed action, queue up a message that will reset the timezone
10655 * of all currently running processes. This message will get queued up before the broadcast
10656 * happens.
10657 */
10658 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10659 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10660 }
10661
Robert Greenwalt03595d02010-11-02 14:08:23 -070010662 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10663 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10664 }
10665
Robert Greenwalt434203a2010-10-11 16:00:27 -070010666 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10667 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10668 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10669 }
10670
Dianne Hackborn854060af2009-07-09 18:14:31 -070010671 /*
10672 * Prevent non-system code (defined here to be non-persistent
10673 * processes) from sending protected broadcasts.
10674 */
10675 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10676 || callingUid == Process.SHELL_UID || callingUid == 0) {
10677 // Always okay.
10678 } else if (callerApp == null || !callerApp.persistent) {
10679 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010680 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010681 intent.getAction())) {
10682 String msg = "Permission Denial: not allowed to send broadcast "
10683 + intent.getAction() + " from pid="
10684 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010685 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010686 throw new SecurityException(msg);
10687 }
10688 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010689 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010690 return BROADCAST_SUCCESS;
10691 }
10692 }
10693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010694 // Add to the sticky list if requested.
10695 if (sticky) {
10696 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10697 callingPid, callingUid)
10698 != PackageManager.PERMISSION_GRANTED) {
10699 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10700 + callingPid + ", uid=" + callingUid
10701 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010702 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010703 throw new SecurityException(msg);
10704 }
10705 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010706 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010707 + " and enforce permission " + requiredPermission);
10708 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10709 }
10710 if (intent.getComponent() != null) {
10711 throw new SecurityException(
10712 "Sticky broadcasts can't target a specific component");
10713 }
10714 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10715 if (list == null) {
10716 list = new ArrayList<Intent>();
10717 mStickyBroadcasts.put(intent.getAction(), list);
10718 }
10719 int N = list.size();
10720 int i;
10721 for (i=0; i<N; i++) {
10722 if (intent.filterEquals(list.get(i))) {
10723 // This sticky already exists, replace it.
10724 list.set(i, new Intent(intent));
10725 break;
10726 }
10727 }
10728 if (i >= N) {
10729 list.add(new Intent(intent));
10730 }
10731 }
10732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010733 // Figure out who all will receive this broadcast.
10734 List receivers = null;
10735 List<BroadcastFilter> registeredReceivers = null;
10736 try {
10737 if (intent.getComponent() != null) {
10738 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010739 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010740 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010741 if (ai != null) {
10742 receivers = new ArrayList();
10743 ResolveInfo ri = new ResolveInfo();
10744 ri.activityInfo = ai;
10745 receivers.add(ri);
10746 }
10747 } else {
10748 // Need to resolve the intent to interested receivers...
10749 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10750 == 0) {
10751 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010752 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010753 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010754 }
Mihai Preda074edef2009-05-18 17:13:31 +020010755 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010756 }
10757 } catch (RemoteException ex) {
10758 // pm is in same process, this will never happen.
10759 }
10760
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010761 final boolean replacePending =
10762 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10763
Joe Onorato8a9b2202010-02-26 18:56:32 -080010764 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010765 + " replacePending=" + replacePending);
10766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010767 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10768 if (!ordered && NR > 0) {
10769 // If we are not serializing this broadcast, then send the
10770 // registered receivers separately so they don't wait for the
10771 // components to be launched.
10772 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10773 callerPackage, callingPid, callingUid, requiredPermission,
10774 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010775 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010776 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010777 TAG, "Enqueueing parallel broadcast " + r
10778 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010779 boolean replaced = false;
10780 if (replacePending) {
10781 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10782 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010783 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010784 "***** DROPPING PARALLEL: " + intent);
10785 mParallelBroadcasts.set(i, r);
10786 replaced = true;
10787 break;
10788 }
10789 }
10790 }
10791 if (!replaced) {
10792 mParallelBroadcasts.add(r);
10793 scheduleBroadcastsLocked();
10794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010795 registeredReceivers = null;
10796 NR = 0;
10797 }
10798
10799 // Merge into one list.
10800 int ir = 0;
10801 if (receivers != null) {
10802 // A special case for PACKAGE_ADDED: do not allow the package
10803 // being added to see this broadcast. This prevents them from
10804 // using this as a back door to get run as soon as they are
10805 // installed. Maybe in the future we want to have a special install
10806 // broadcast or such for apps, but we'd like to deliberately make
10807 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010808 String skipPackages[] = null;
10809 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10810 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10811 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10812 Uri data = intent.getData();
10813 if (data != null) {
10814 String pkgName = data.getSchemeSpecificPart();
10815 if (pkgName != null) {
10816 skipPackages = new String[] { pkgName };
10817 }
10818 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010819 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010820 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010821 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010822 if (skipPackages != null && (skipPackages.length > 0)) {
10823 for (String skipPackage : skipPackages) {
10824 if (skipPackage != null) {
10825 int NT = receivers.size();
10826 for (int it=0; it<NT; it++) {
10827 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10828 if (curt.activityInfo.packageName.equals(skipPackage)) {
10829 receivers.remove(it);
10830 it--;
10831 NT--;
10832 }
10833 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010834 }
10835 }
10836 }
10837
10838 int NT = receivers != null ? receivers.size() : 0;
10839 int it = 0;
10840 ResolveInfo curt = null;
10841 BroadcastFilter curr = null;
10842 while (it < NT && ir < NR) {
10843 if (curt == null) {
10844 curt = (ResolveInfo)receivers.get(it);
10845 }
10846 if (curr == null) {
10847 curr = registeredReceivers.get(ir);
10848 }
10849 if (curr.getPriority() >= curt.priority) {
10850 // Insert this broadcast record into the final list.
10851 receivers.add(it, curr);
10852 ir++;
10853 curr = null;
10854 it++;
10855 NT++;
10856 } else {
10857 // Skip to the next ResolveInfo in the final list.
10858 it++;
10859 curt = null;
10860 }
10861 }
10862 }
10863 while (ir < NR) {
10864 if (receivers == null) {
10865 receivers = new ArrayList();
10866 }
10867 receivers.add(registeredReceivers.get(ir));
10868 ir++;
10869 }
10870
10871 if ((receivers != null && receivers.size() > 0)
10872 || resultTo != null) {
10873 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10874 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010875 receivers, resultTo, resultCode, resultData, map, ordered,
10876 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010877 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010878 TAG, "Enqueueing ordered broadcast " + r
10879 + ": prev had " + mOrderedBroadcasts.size());
10880 if (DEBUG_BROADCAST) {
10881 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010882 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010883 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010884 boolean replaced = false;
10885 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010886 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010887 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010888 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010889 "***** DROPPING ORDERED: " + intent);
10890 mOrderedBroadcasts.set(i, r);
10891 replaced = true;
10892 break;
10893 }
10894 }
10895 }
10896 if (!replaced) {
10897 mOrderedBroadcasts.add(r);
10898 scheduleBroadcastsLocked();
10899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010900 }
10901
10902 return BROADCAST_SUCCESS;
10903 }
10904
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010905 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 // Refuse possible leaked file descriptors
10907 if (intent != null && intent.hasFileDescriptors() == true) {
10908 throw new IllegalArgumentException("File descriptors passed in Intent");
10909 }
10910
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010911 int flags = intent.getFlags();
10912
10913 if (!mProcessesReady) {
10914 // if the caller really truly claims to know what they're doing, go
10915 // ahead and allow the broadcast without launching any receivers
10916 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10917 intent = new Intent(intent);
10918 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10919 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10920 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10921 + " before boot completion");
10922 throw new IllegalStateException("Cannot broadcast before boot completed");
10923 }
10924 }
10925
10926 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10927 throw new IllegalArgumentException(
10928 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10929 }
10930
10931 return intent;
10932 }
10933
10934 public final int broadcastIntent(IApplicationThread caller,
10935 Intent intent, String resolvedType, IIntentReceiver resultTo,
10936 int resultCode, String resultData, Bundle map,
10937 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010939 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010941 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10942 final int callingPid = Binder.getCallingPid();
10943 final int callingUid = Binder.getCallingUid();
10944 final long origId = Binder.clearCallingIdentity();
10945 int res = broadcastIntentLocked(callerApp,
10946 callerApp != null ? callerApp.info.packageName : null,
10947 intent, resolvedType, resultTo,
10948 resultCode, resultData, map, requiredPermission, serialized,
10949 sticky, callingPid, callingUid);
10950 Binder.restoreCallingIdentity(origId);
10951 return res;
10952 }
10953 }
10954
10955 int broadcastIntentInPackage(String packageName, int uid,
10956 Intent intent, String resolvedType, IIntentReceiver resultTo,
10957 int resultCode, String resultData, Bundle map,
10958 String requiredPermission, boolean serialized, boolean sticky) {
10959 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010960 intent = verifyBroadcastLocked(intent);
10961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010962 final long origId = Binder.clearCallingIdentity();
10963 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10964 resultTo, resultCode, resultData, map, requiredPermission,
10965 serialized, sticky, -1, uid);
10966 Binder.restoreCallingIdentity(origId);
10967 return res;
10968 }
10969 }
10970
10971 public final void unbroadcastIntent(IApplicationThread caller,
10972 Intent intent) {
10973 // Refuse possible leaked file descriptors
10974 if (intent != null && intent.hasFileDescriptors() == true) {
10975 throw new IllegalArgumentException("File descriptors passed in Intent");
10976 }
10977
10978 synchronized(this) {
10979 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10980 != PackageManager.PERMISSION_GRANTED) {
10981 String msg = "Permission Denial: unbroadcastIntent() from pid="
10982 + Binder.getCallingPid()
10983 + ", uid=" + Binder.getCallingUid()
10984 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010985 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010986 throw new SecurityException(msg);
10987 }
10988 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10989 if (list != null) {
10990 int N = list.size();
10991 int i;
10992 for (i=0; i<N; i++) {
10993 if (intent.filterEquals(list.get(i))) {
10994 list.remove(i);
10995 break;
10996 }
10997 }
10998 }
10999 }
11000 }
11001
11002 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11003 String resultData, Bundle resultExtras, boolean resultAbort,
11004 boolean explicit) {
11005 if (mOrderedBroadcasts.size() == 0) {
11006 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011007 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 }
11009 return false;
11010 }
11011 BroadcastRecord r = mOrderedBroadcasts.get(0);
11012 if (r.receiver == null) {
11013 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011014 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011015 }
11016 return false;
11017 }
11018 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011019 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011020 return false;
11021 }
11022 int state = r.state;
11023 r.state = r.IDLE;
11024 if (state == r.IDLE) {
11025 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011026 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011027 }
11028 }
11029 r.receiver = null;
11030 r.intent.setComponent(null);
11031 if (r.curApp != null) {
11032 r.curApp.curReceiver = null;
11033 }
11034 if (r.curFilter != null) {
11035 r.curFilter.receiverList.curBroadcast = null;
11036 }
11037 r.curFilter = null;
11038 r.curApp = null;
11039 r.curComponent = null;
11040 r.curReceiver = null;
11041 mPendingBroadcast = null;
11042
11043 r.resultCode = resultCode;
11044 r.resultData = resultData;
11045 r.resultExtras = resultExtras;
11046 r.resultAbort = resultAbort;
11047
11048 // We will process the next receiver right now if this is finishing
11049 // an app receiver (which is always asynchronous) or after we have
11050 // come back from calling a receiver.
11051 return state == BroadcastRecord.APP_RECEIVE
11052 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11053 }
11054
11055 public void finishReceiver(IBinder who, int resultCode, String resultData,
11056 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011057 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011058
11059 // Refuse possible leaked file descriptors
11060 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11061 throw new IllegalArgumentException("File descriptors passed in Bundle");
11062 }
11063
11064 boolean doNext;
11065
11066 final long origId = Binder.clearCallingIdentity();
11067
11068 synchronized(this) {
11069 doNext = finishReceiverLocked(
11070 who, resultCode, resultData, resultExtras, resultAbort, true);
11071 }
11072
11073 if (doNext) {
11074 processNextBroadcast(false);
11075 }
11076 trimApplications();
11077
11078 Binder.restoreCallingIdentity(origId);
11079 }
11080
Jeff Brown4d94a762010-09-23 11:33:28 -070011081 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011082 if (r.nextReceiver > 0) {
11083 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11084 if (curReceiver instanceof BroadcastFilter) {
11085 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011086 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087 System.identityHashCode(r),
11088 r.intent.getAction(),
11089 r.nextReceiver - 1,
11090 System.identityHashCode(bf));
11091 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011092 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011093 System.identityHashCode(r),
11094 r.intent.getAction(),
11095 r.nextReceiver - 1,
11096 ((ResolveInfo)curReceiver).toString());
11097 }
11098 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011099 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011100 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011101 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011102 System.identityHashCode(r),
11103 r.intent.getAction(),
11104 r.nextReceiver,
11105 "NONE");
11106 }
11107 }
11108
Jeff Brown4d94a762010-09-23 11:33:28 -070011109 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11110 if (! mPendingBroadcastTimeoutMessage) {
11111 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11112 mHandler.sendMessageAtTime(msg, timeoutTime);
11113 mPendingBroadcastTimeoutMessage = true;
11114 }
11115 }
11116
11117 private final void cancelBroadcastTimeoutLocked() {
11118 if (mPendingBroadcastTimeoutMessage) {
11119 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11120 mPendingBroadcastTimeoutMessage = false;
11121 }
11122 }
11123
11124 private final void broadcastTimeoutLocked(boolean fromMsg) {
11125 if (fromMsg) {
11126 mPendingBroadcastTimeoutMessage = false;
11127 }
11128
11129 if (mOrderedBroadcasts.size() == 0) {
11130 return;
11131 }
11132
11133 long now = SystemClock.uptimeMillis();
11134 BroadcastRecord r = mOrderedBroadcasts.get(0);
11135 if (fromMsg) {
11136 if (mDidDexOpt) {
11137 // Delay timeouts until dexopt finishes.
11138 mDidDexOpt = false;
11139 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11140 setBroadcastTimeoutLocked(timeoutTime);
11141 return;
11142 }
11143 if (! mProcessesReady) {
11144 // Only process broadcast timeouts if the system is ready. That way
11145 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11146 // to do heavy lifting for system up.
11147 return;
11148 }
11149
11150 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11151 if (timeoutTime > now) {
11152 // We can observe premature timeouts because we do not cancel and reset the
11153 // broadcast timeout message after each receiver finishes. Instead, we set up
11154 // an initial timeout then kick it down the road a little further as needed
11155 // when it expires.
11156 if (DEBUG_BROADCAST) Slog.v(TAG,
11157 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11158 + timeoutTime);
11159 setBroadcastTimeoutLocked(timeoutTime);
11160 return;
11161 }
11162 }
11163
11164 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11165 + ", started " + (now - r.receiverTime) + "ms ago");
11166 r.receiverTime = now;
11167 r.anrCount++;
11168
11169 // Current receiver has passed its expiration date.
11170 if (r.nextReceiver <= 0) {
11171 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11172 return;
11173 }
11174
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011175 ProcessRecord app = null;
11176 String anrMessage = null;
11177
Jeff Brown4d94a762010-09-23 11:33:28 -070011178 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11179 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11180 logBroadcastReceiverDiscardLocked(r);
11181 if (curReceiver instanceof BroadcastFilter) {
11182 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11183 if (bf.receiverList.pid != 0
11184 && bf.receiverList.pid != MY_PID) {
11185 synchronized (this.mPidsSelfLocked) {
11186 app = this.mPidsSelfLocked.get(
11187 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011189 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011190 } else {
11191 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011193
Jeff Brown4d94a762010-09-23 11:33:28 -070011194 if (app != null) {
11195 anrMessage = "Broadcast of " + r.intent.toString();
11196 }
11197
11198 if (mPendingBroadcast == r) {
11199 mPendingBroadcast = null;
11200 }
11201
11202 // Move on to the next receiver.
11203 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11204 r.resultExtras, r.resultAbort, true);
11205 scheduleBroadcastsLocked();
11206
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011207 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011208 // Post the ANR to the handler since we do not want to process ANRs while
11209 // potentially holding our lock.
11210 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011212 }
11213
11214 private final void processCurBroadcastLocked(BroadcastRecord r,
11215 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011216 if (DEBUG_BROADCAST) Slog.v(TAG,
11217 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011218 if (app.thread == null) {
11219 throw new RemoteException();
11220 }
11221 r.receiver = app.thread.asBinder();
11222 r.curApp = app;
11223 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011224 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011225
11226 // Tell the application to launch this receiver.
11227 r.intent.setComponent(r.curComponent);
11228
11229 boolean started = false;
11230 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011231 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011232 "Delivering to component " + r.curComponent
11233 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011234 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11236 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011237 if (DEBUG_BROADCAST) Slog.v(TAG,
11238 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011239 started = true;
11240 } finally {
11241 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011242 if (DEBUG_BROADCAST) Slog.v(TAG,
11243 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011244 r.receiver = null;
11245 r.curApp = null;
11246 app.curReceiver = null;
11247 }
11248 }
11249
11250 }
11251
Jeff Brown4d94a762010-09-23 11:33:28 -070011252 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011253 Intent intent, int resultCode, String data, Bundle extras,
11254 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011255 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011256 if (app != null && app.thread != null) {
11257 // If we have an app thread, do the call through that so it is
11258 // correctly ordered with other one-way calls.
11259 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011260 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011261 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011262 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 }
11264 }
11265
Jeff Brown4d94a762010-09-23 11:33:28 -070011266 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 BroadcastFilter filter, boolean ordered) {
11268 boolean skip = false;
11269 if (filter.requiredPermission != null) {
11270 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011271 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011272 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011273 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 + r.intent.toString()
11275 + " from " + r.callerPackage + " (pid="
11276 + r.callingPid + ", uid=" + r.callingUid + ")"
11277 + " requires " + filter.requiredPermission
11278 + " due to registered receiver " + filter);
11279 skip = true;
11280 }
11281 }
11282 if (r.requiredPermission != null) {
11283 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011284 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011286 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011287 + r.intent.toString()
11288 + " to " + filter.receiverList.app
11289 + " (pid=" + filter.receiverList.pid
11290 + ", uid=" + filter.receiverList.uid + ")"
11291 + " requires " + r.requiredPermission
11292 + " due to sender " + r.callerPackage
11293 + " (uid " + r.callingUid + ")");
11294 skip = true;
11295 }
11296 }
11297
11298 if (!skip) {
11299 // If this is not being sent as an ordered broadcast, then we
11300 // don't want to touch the fields that keep track of the current
11301 // state of ordered broadcasts.
11302 if (ordered) {
11303 r.receiver = filter.receiverList.receiver.asBinder();
11304 r.curFilter = filter;
11305 filter.receiverList.curBroadcast = r;
11306 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011307 if (filter.receiverList.app != null) {
11308 // Bump hosting application to no longer be in background
11309 // scheduling class. Note that we can't do that if there
11310 // isn't an app... but we can only be in that case for
11311 // things that directly call the IActivityManager API, which
11312 // are already core system stuff so don't matter for this.
11313 r.curApp = filter.receiverList.app;
11314 filter.receiverList.app.curReceiver = r;
11315 updateOomAdjLocked();
11316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011317 }
11318 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011319 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011320 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011321 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011322 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011323 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011324 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011325 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011326 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011327 if (ordered) {
11328 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11329 }
11330 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011331 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011332 if (ordered) {
11333 r.receiver = null;
11334 r.curFilter = null;
11335 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011336 if (filter.receiverList.app != null) {
11337 filter.receiverList.app.curReceiver = null;
11338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011339 }
11340 }
11341 }
11342 }
11343
Dianne Hackborn12527f92009-11-11 17:39:50 -080011344 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11345 if (r.callingUid < 0) {
11346 // This was from a registerReceiver() call; ignore it.
11347 return;
11348 }
11349 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11350 MAX_BROADCAST_HISTORY-1);
11351 r.finishTime = SystemClock.uptimeMillis();
11352 mBroadcastHistory[0] = r;
11353 }
11354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011355 private final void processNextBroadcast(boolean fromMsg) {
11356 synchronized(this) {
11357 BroadcastRecord r;
11358
Joe Onorato8a9b2202010-02-26 18:56:32 -080011359 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011361 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362
11363 updateCpuStats();
11364
11365 if (fromMsg) {
11366 mBroadcastsScheduled = false;
11367 }
11368
11369 // First, deliver any non-serialized broadcasts right away.
11370 while (mParallelBroadcasts.size() > 0) {
11371 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011372 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011373 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011374 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011375 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011376 for (int i=0; i<N; i++) {
11377 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011378 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011379 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011380 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011381 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011382 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011383 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011384 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011385 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011386 }
11387
11388 // Now take care of the next serialized one...
11389
11390 // If we are waiting for a process to come up to handle the next
11391 // broadcast, then do nothing at this point. Just in case, we
11392 // check that the process we're waiting for still exists.
11393 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011394 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011395 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011396 + mPendingBroadcast.curApp);
11397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011398
11399 boolean isDead;
11400 synchronized (mPidsSelfLocked) {
11401 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11402 }
11403 if (!isDead) {
11404 // It's still alive, so keep waiting
11405 return;
11406 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011407 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011409 mPendingBroadcast.state = BroadcastRecord.IDLE;
11410 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011411 mPendingBroadcast = null;
11412 }
11413 }
11414
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011415 boolean looped = false;
11416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011417 do {
11418 if (mOrderedBroadcasts.size() == 0) {
11419 // No more broadcasts pending, so all done!
11420 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011421 if (looped) {
11422 // If we had finished the last ordered broadcast, then
11423 // make sure all processes have correct oom and sched
11424 // adjustments.
11425 updateOomAdjLocked();
11426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011427 return;
11428 }
11429 r = mOrderedBroadcasts.get(0);
11430 boolean forceReceive = false;
11431
11432 // Ensure that even if something goes awry with the timeout
11433 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011434 // and continue to make progress.
11435 //
11436 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011437 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011438 // one time heavy lifting after system upgrades and can take
11439 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011440 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011441 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011442 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011443 if ((numReceivers > 0) &&
11444 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011445 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011446 + " now=" + now
11447 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011448 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011449 + " intent=" + r.intent
11450 + " numReceivers=" + numReceivers
11451 + " nextReceiver=" + r.nextReceiver
11452 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011453 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011454 forceReceive = true;
11455 r.state = BroadcastRecord.IDLE;
11456 }
11457 }
11458
11459 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011460 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011461 "processNextBroadcast() called when not idle (state="
11462 + r.state + ")");
11463 return;
11464 }
11465
11466 if (r.receivers == null || r.nextReceiver >= numReceivers
11467 || r.resultAbort || forceReceive) {
11468 // No more receivers for this broadcast! Send the final
11469 // result if requested...
11470 if (r.resultTo != null) {
11471 try {
11472 if (DEBUG_BROADCAST) {
11473 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011474 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011475 + " seq=" + seq + " app=" + r.callerApp);
11476 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011477 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011478 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011479 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011480 // Set this to null so that the reference
11481 // (local and remote) isnt kept in the mBroadcastHistory.
11482 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011483 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011484 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 }
11486 }
11487
Joe Onorato8a9b2202010-02-26 18:56:32 -080011488 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011489 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011490
Joe Onorato8a9b2202010-02-26 18:56:32 -080011491 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011492 + r);
11493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011494 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011495 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011496 mOrderedBroadcasts.remove(0);
11497 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011498 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011499 continue;
11500 }
11501 } while (r == null);
11502
11503 // Get the next receiver...
11504 int recIdx = r.nextReceiver++;
11505
11506 // Keep track of when this receiver started, and make sure there
11507 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011508 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011509 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011510 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511
Joe Onorato8a9b2202010-02-26 18:56:32 -080011512 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011513 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011514 }
11515 if (! mPendingBroadcastTimeoutMessage) {
11516 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011517 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011518 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11519 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011520 }
11521
11522 Object nextReceiver = r.receivers.get(recIdx);
11523 if (nextReceiver instanceof BroadcastFilter) {
11524 // Simple case: this is a registered receiver who gets
11525 // a direct call.
11526 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011527 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011528 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011529 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011530 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011531 if (r.receiver == null || !r.ordered) {
11532 // The receiver has already finished, so schedule to
11533 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011534 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11535 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011536 r.state = BroadcastRecord.IDLE;
11537 scheduleBroadcastsLocked();
11538 }
11539 return;
11540 }
11541
11542 // Hard case: need to instantiate the receiver, possibly
11543 // starting its application process to host it.
11544
11545 ResolveInfo info =
11546 (ResolveInfo)nextReceiver;
11547
11548 boolean skip = false;
11549 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011550 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
11551 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011552 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011553 if (!info.activityInfo.exported) {
11554 Slog.w(TAG, "Permission Denial: broadcasting "
11555 + r.intent.toString()
11556 + " from " + r.callerPackage + " (pid=" + r.callingPid
11557 + ", uid=" + r.callingUid + ")"
11558 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
11559 + " due to receiver " + info.activityInfo.packageName
11560 + "/" + info.activityInfo.name);
11561 } else {
11562 Slog.w(TAG, "Permission Denial: broadcasting "
11563 + r.intent.toString()
11564 + " from " + r.callerPackage + " (pid=" + r.callingPid
11565 + ", uid=" + r.callingUid + ")"
11566 + " requires " + info.activityInfo.permission
11567 + " due to receiver " + info.activityInfo.packageName
11568 + "/" + info.activityInfo.name);
11569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011570 skip = true;
11571 }
11572 if (r.callingUid != Process.SYSTEM_UID &&
11573 r.requiredPermission != null) {
11574 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011575 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576 checkPermission(r.requiredPermission,
11577 info.activityInfo.applicationInfo.packageName);
11578 } catch (RemoteException e) {
11579 perm = PackageManager.PERMISSION_DENIED;
11580 }
11581 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011582 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011583 + r.intent + " to "
11584 + info.activityInfo.applicationInfo.packageName
11585 + " requires " + r.requiredPermission
11586 + " due to sender " + r.callerPackage
11587 + " (uid " + r.callingUid + ")");
11588 skip = true;
11589 }
11590 }
11591 if (r.curApp != null && r.curApp.crashing) {
11592 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011593 if (DEBUG_BROADCAST) Slog.v(TAG,
11594 "Skipping deliver ordered " + r + " to " + r.curApp
11595 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011596 skip = true;
11597 }
11598
11599 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011600 if (DEBUG_BROADCAST) Slog.v(TAG,
11601 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011602 r.receiver = null;
11603 r.curFilter = null;
11604 r.state = BroadcastRecord.IDLE;
11605 scheduleBroadcastsLocked();
11606 return;
11607 }
11608
11609 r.state = BroadcastRecord.APP_RECEIVE;
11610 String targetProcess = info.activityInfo.processName;
11611 r.curComponent = new ComponentName(
11612 info.activityInfo.applicationInfo.packageName,
11613 info.activityInfo.name);
11614 r.curReceiver = info.activityInfo;
11615
Dianne Hackborne7f97212011-02-24 14:40:20 -080011616 // Broadcast is being executed, its package can't be stopped.
11617 try {
11618 AppGlobals.getPackageManager().setPackageStoppedState(
11619 r.curComponent.getPackageName(), false);
11620 } catch (RemoteException e) {
11621 }
11622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011623 // Is this receiver's application already running?
11624 ProcessRecord app = getProcessRecordLocked(targetProcess,
11625 info.activityInfo.applicationInfo.uid);
11626 if (app != null && app.thread != null) {
11627 try {
11628 processCurBroadcastLocked(r, app);
11629 return;
11630 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011631 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011632 + r.curComponent, e);
11633 }
11634
11635 // If a dead object exception was thrown -- fall through to
11636 // restart the application.
11637 }
11638
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011639 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011640 if (DEBUG_BROADCAST) Slog.v(TAG,
11641 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011642 if ((r.curApp=startProcessLocked(targetProcess,
11643 info.activityInfo.applicationInfo, true,
11644 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011645 "broadcast", r.curComponent,
11646 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11647 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011648 // Ah, this recipient is unavailable. Finish it if necessary,
11649 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011650 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011651 + info.activityInfo.applicationInfo.packageName + "/"
11652 + info.activityInfo.applicationInfo.uid + " for broadcast "
11653 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011654 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011655 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11656 r.resultExtras, r.resultAbort, true);
11657 scheduleBroadcastsLocked();
11658 r.state = BroadcastRecord.IDLE;
11659 return;
11660 }
11661
11662 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011663 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011664 }
11665 }
11666
11667 // =========================================================
11668 // INSTRUMENTATION
11669 // =========================================================
11670
11671 public boolean startInstrumentation(ComponentName className,
11672 String profileFile, int flags, Bundle arguments,
11673 IInstrumentationWatcher watcher) {
11674 // Refuse possible leaked file descriptors
11675 if (arguments != null && arguments.hasFileDescriptors()) {
11676 throw new IllegalArgumentException("File descriptors passed in Bundle");
11677 }
11678
11679 synchronized(this) {
11680 InstrumentationInfo ii = null;
11681 ApplicationInfo ai = null;
11682 try {
11683 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011684 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011685 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011686 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011687 } catch (PackageManager.NameNotFoundException e) {
11688 }
11689 if (ii == null) {
11690 reportStartInstrumentationFailure(watcher, className,
11691 "Unable to find instrumentation info for: " + className);
11692 return false;
11693 }
11694 if (ai == null) {
11695 reportStartInstrumentationFailure(watcher, className,
11696 "Unable to find instrumentation target package: " + ii.targetPackage);
11697 return false;
11698 }
11699
11700 int match = mContext.getPackageManager().checkSignatures(
11701 ii.targetPackage, ii.packageName);
11702 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11703 String msg = "Permission Denial: starting instrumentation "
11704 + className + " from pid="
11705 + Binder.getCallingPid()
11706 + ", uid=" + Binder.getCallingPid()
11707 + " not allowed because package " + ii.packageName
11708 + " does not have a signature matching the target "
11709 + ii.targetPackage;
11710 reportStartInstrumentationFailure(watcher, className, msg);
11711 throw new SecurityException(msg);
11712 }
11713
11714 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011715 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011716 ProcessRecord app = addAppLocked(ai);
11717 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011718 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011719 app.instrumentationProfileFile = profileFile;
11720 app.instrumentationArguments = arguments;
11721 app.instrumentationWatcher = watcher;
11722 app.instrumentationResultClass = className;
11723 Binder.restoreCallingIdentity(origId);
11724 }
11725
11726 return true;
11727 }
11728
11729 /**
11730 * Report errors that occur while attempting to start Instrumentation. Always writes the
11731 * error to the logs, but if somebody is watching, send the report there too. This enables
11732 * the "am" command to report errors with more information.
11733 *
11734 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11735 * @param cn The component name of the instrumentation.
11736 * @param report The error report.
11737 */
11738 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11739 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011740 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011741 try {
11742 if (watcher != null) {
11743 Bundle results = new Bundle();
11744 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11745 results.putString("Error", report);
11746 watcher.instrumentationStatus(cn, -1, results);
11747 }
11748 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011749 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011750 }
11751 }
11752
11753 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11754 if (app.instrumentationWatcher != null) {
11755 try {
11756 // NOTE: IInstrumentationWatcher *must* be oneway here
11757 app.instrumentationWatcher.instrumentationFinished(
11758 app.instrumentationClass,
11759 resultCode,
11760 results);
11761 } catch (RemoteException e) {
11762 }
11763 }
11764 app.instrumentationWatcher = null;
11765 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011766 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011767 app.instrumentationProfileFile = null;
11768 app.instrumentationArguments = null;
11769
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011770 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 }
11772
11773 public void finishInstrumentation(IApplicationThread target,
11774 int resultCode, Bundle results) {
11775 // Refuse possible leaked file descriptors
11776 if (results != null && results.hasFileDescriptors()) {
11777 throw new IllegalArgumentException("File descriptors passed in Intent");
11778 }
11779
11780 synchronized(this) {
11781 ProcessRecord app = getRecordForAppLocked(target);
11782 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011783 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011784 return;
11785 }
11786 final long origId = Binder.clearCallingIdentity();
11787 finishInstrumentationLocked(app, resultCode, results);
11788 Binder.restoreCallingIdentity(origId);
11789 }
11790 }
11791
11792 // =========================================================
11793 // CONFIGURATION
11794 // =========================================================
11795
11796 public ConfigurationInfo getDeviceConfigurationInfo() {
11797 ConfigurationInfo config = new ConfigurationInfo();
11798 synchronized (this) {
11799 config.reqTouchScreen = mConfiguration.touchscreen;
11800 config.reqKeyboardType = mConfiguration.keyboard;
11801 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011802 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11803 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11805 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011806 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11807 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011808 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11809 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011810 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011811 }
11812 return config;
11813 }
11814
11815 public Configuration getConfiguration() {
11816 Configuration ci;
11817 synchronized(this) {
11818 ci = new Configuration(mConfiguration);
11819 }
11820 return ci;
11821 }
11822
11823 public void updateConfiguration(Configuration values) {
11824 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11825 "updateConfiguration()");
11826
11827 synchronized(this) {
11828 if (values == null && mWindowManager != null) {
11829 // sentinel: fetch the current configuration from the window manager
11830 values = mWindowManager.computeNewConfiguration();
11831 }
11832
11833 final long origId = Binder.clearCallingIdentity();
11834 updateConfigurationLocked(values, null);
11835 Binder.restoreCallingIdentity(origId);
11836 }
11837 }
11838
11839 /**
11840 * Do either or both things: (1) change the current configuration, and (2)
11841 * make sure the given activity is running with the (now) current
11842 * configuration. Returns true if the activity has been left running, or
11843 * false if <var>starting</var> is being destroyed to match the new
11844 * configuration.
11845 */
11846 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011847 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011848 int changes = 0;
11849
11850 boolean kept = true;
11851
11852 if (values != null) {
11853 Configuration newConfig = new Configuration(mConfiguration);
11854 changes = newConfig.updateFrom(values);
11855 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011856 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011857 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011858 }
11859
Doug Zongker2bec3d42009-12-04 12:52:44 -080011860 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011861
11862 if (values.locale != null) {
11863 saveLocaleLocked(values.locale,
11864 !values.locale.equals(mConfiguration.locale),
11865 values.userSetLocale);
11866 }
11867
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011868 mConfigurationSeq++;
11869 if (mConfigurationSeq <= 0) {
11870 mConfigurationSeq = 1;
11871 }
11872 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011873 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011874 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011875
11876 AttributeCache ac = AttributeCache.instance();
11877 if (ac != null) {
11878 ac.updateConfiguration(mConfiguration);
11879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011880
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011881 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11882 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11883 msg.obj = new Configuration(mConfiguration);
11884 mHandler.sendMessage(msg);
11885 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011886
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011887 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11888 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011889 try {
11890 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011891 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011892 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011893 app.thread.scheduleConfigurationChanged(mConfiguration);
11894 }
11895 } catch (Exception e) {
11896 }
11897 }
11898 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011899 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11900 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011901 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11902 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011903 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11904 broadcastIntentLocked(null, null,
11905 new Intent(Intent.ACTION_LOCALE_CHANGED),
11906 null, null, 0, null, null,
11907 null, false, false, MY_PID, Process.SYSTEM_UID);
11908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011909 }
11910 }
11911
11912 if (changes != 0 && starting == null) {
11913 // If the configuration changed, and the caller is not already
11914 // in the process of starting an activity, then find the top
11915 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011916 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011917 }
11918
11919 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011920 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080011921 // And we need to make sure at this point that all other activities
11922 // are made visible with the correct configuration.
11923 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011924 }
11925
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011926 if (values != null && mWindowManager != null) {
11927 mWindowManager.setNewConfiguration(mConfiguration);
11928 }
11929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011930 return kept;
11931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011932
11933 /**
11934 * Save the locale. You must be inside a synchronized (this) block.
11935 */
11936 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11937 if(isDiff) {
11938 SystemProperties.set("user.language", l.getLanguage());
11939 SystemProperties.set("user.region", l.getCountry());
11940 }
11941
11942 if(isPersist) {
11943 SystemProperties.set("persist.sys.language", l.getLanguage());
11944 SystemProperties.set("persist.sys.country", l.getCountry());
11945 SystemProperties.set("persist.sys.localevar", l.getVariant());
11946 }
11947 }
11948
11949 // =========================================================
11950 // LIFETIME MANAGEMENT
11951 // =========================================================
11952
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011953 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11954 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011955 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011956 // This adjustment has already been computed. If we are calling
11957 // from the top, we may have already computed our adjustment with
11958 // an earlier hidden adjustment that isn't really for us... if
11959 // so, use the new hidden adjustment.
11960 if (!recursed && app.hidden) {
11961 app.curAdj = hiddenAdj;
11962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011963 return app.curAdj;
11964 }
11965
11966 if (app.thread == null) {
11967 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011968 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011969 return (app.curAdj=EMPTY_APP_ADJ);
11970 }
11971
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011972 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11973 // The max adjustment doesn't allow this app to be anything
11974 // below foreground, so it is not worth doing work for it.
11975 app.adjType = "fixed";
11976 app.adjSeq = mAdjSeq;
11977 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011978 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011979 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11980 return (app.curAdj=app.maxAdj);
11981 }
11982
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011983 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011984 app.adjSource = null;
11985 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011986 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011987 app.empty = false;
11988 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011989
The Android Open Source Project4df24232009-03-05 14:34:35 -080011990 // Determine the importance of the process, starting with most
11991 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011992 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011993 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011994 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011995 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011996 // The last app on the list is the foreground app.
11997 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011998 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011999 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012000 } else if (app.instrumentationClass != null) {
12001 // Don't want to kill running instrumentation.
12002 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012003 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012004 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012005 } else if (app.curReceiver != null ||
12006 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12007 // An app that is currently receiving a broadcast also
12008 // counts as being in the foreground.
12009 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012010 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012011 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012012 } else if (app.executingServices.size() > 0) {
12013 // An app that is currently executing a service callback also
12014 // counts as being in the foreground.
12015 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012016 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012017 app.adjType = "exec-service";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012018 } else if ((N=app.activities.size()) != 0) {
12019 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012020 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012021 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012022 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012023 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012024 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012025 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012026 ActivityRecord r = app.activities.get(j);
12027 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012028 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012029 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012030 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012031 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012032 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012033 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012034 } else if (r.state == ActivityState.PAUSING
12035 || r.state == ActivityState.PAUSED
12036 || r.state == ActivityState.STOPPING) {
12037 adj = PERCEPTIBLE_APP_ADJ;
12038 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012039 }
12040 }
12041 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012042 // A very not-needed process. If this is lower in the lru list,
12043 // we will push it in to the empty bucket.
12044 app.hidden = true;
12045 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012046 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012047 adj = hiddenAdj;
12048 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012049 }
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012050
12051 if (adj > PERCEPTIBLE_APP_ADJ) {
12052 if (app.foregroundServices) {
12053 // The user is aware of this app, so make it visible.
12054 adj = PERCEPTIBLE_APP_ADJ;
12055 schedGroup = Process.THREAD_GROUP_DEFAULT;
12056 app.adjType = "foreground-service";
12057 } else if (app.forcingToForeground != null) {
12058 // The user is aware of this app, so make it visible.
12059 adj = PERCEPTIBLE_APP_ADJ;
12060 schedGroup = Process.THREAD_GROUP_DEFAULT;
12061 app.adjType = "force-foreground";
12062 app.adjSource = app.forcingToForeground;
12063 }
12064 }
12065
12066 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12067 // We don't want to kill the current heavy-weight process.
12068 adj = HEAVY_WEIGHT_APP_ADJ;
12069 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12070 app.adjType = "heavy";
12071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012072
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012073 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12074 // This process is hosting what we currently consider to be the
12075 // home app, so we don't want to let it go into the background.
12076 adj = HOME_APP_ADJ;
12077 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12078 app.adjType = "home";
12079 }
12080
Joe Onorato8a9b2202010-02-26 18:56:32 -080012081 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012082
The Android Open Source Project4df24232009-03-05 14:34:35 -080012083 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012084 // there are applications dependent on our services or providers, but
12085 // this gives us a baseline and makes sure we don't get into an
12086 // infinite recursion.
12087 app.adjSeq = mAdjSeq;
12088 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089
Christopher Tate6fa95972009-06-05 18:43:55 -070012090 if (mBackupTarget != null && app == mBackupTarget.app) {
12091 // If possible we want to avoid killing apps while they're being backed up
12092 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012093 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012094 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012095 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012096 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012097 }
12098 }
12099
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012100 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12101 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012102 final long now = SystemClock.uptimeMillis();
12103 // This process is more important if the top activity is
12104 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012105 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012106 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012107 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012108 if (s.startRequested) {
12109 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12110 // This service has seen some activity within
12111 // recent memory, so we will keep its process ahead
12112 // of the background processes.
12113 if (adj > SECONDARY_SERVER_ADJ) {
12114 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012115 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012116 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012117 }
12118 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012119 // If we have let the service slide into the background
12120 // state, still have some text describing what it is doing
12121 // even though the service no longer has an impact.
12122 if (adj > SECONDARY_SERVER_ADJ) {
12123 app.adjType = "started-bg-services";
12124 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012125 // Don't kill this process because it is doing work; it
12126 // has said it is doing work.
12127 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012128 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012129 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12130 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012131 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012132 = s.connections.values().iterator();
12133 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012134 ArrayList<ConnectionRecord> clist = kt.next();
12135 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12136 // XXX should compute this based on the max of
12137 // all connected clients.
12138 ConnectionRecord cr = clist.get(i);
12139 if (cr.binding.client == app) {
12140 // Binding to ourself is not interesting.
12141 continue;
12142 }
12143 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12144 ProcessRecord client = cr.binding.client;
12145 int myHiddenAdj = hiddenAdj;
12146 if (myHiddenAdj > client.hiddenAdj) {
12147 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12148 myHiddenAdj = client.hiddenAdj;
12149 } else {
12150 myHiddenAdj = VISIBLE_APP_ADJ;
12151 }
12152 }
12153 int clientAdj = computeOomAdjLocked(
12154 client, myHiddenAdj, TOP_APP, true);
12155 if (adj > clientAdj) {
12156 adj = clientAdj >= VISIBLE_APP_ADJ
12157 ? clientAdj : VISIBLE_APP_ADJ;
12158 if (!client.hidden) {
12159 app.hidden = false;
12160 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012161 if (client.keeping) {
12162 app.keeping = true;
12163 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012164 app.adjType = "service";
12165 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12166 .REASON_SERVICE_IN_USE;
12167 app.adjSource = cr.binding.client;
12168 app.adjTarget = s.name;
12169 }
12170 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12171 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12172 schedGroup = Process.THREAD_GROUP_DEFAULT;
12173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012174 }
12175 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012176 ActivityRecord a = cr.activity;
12177 //if (a != null) {
12178 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12179 //}
12180 if (a != null && adj > FOREGROUND_APP_ADJ &&
12181 (a.state == ActivityState.RESUMED
12182 || a.state == ActivityState.PAUSING)) {
12183 adj = FOREGROUND_APP_ADJ;
12184 schedGroup = Process.THREAD_GROUP_DEFAULT;
12185 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012186 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012187 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12188 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012189 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012190 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012192 }
12193 }
12194 }
12195 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012196
Dianne Hackborn287952c2010-09-22 22:34:31 -070012197 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012198 // would like to avoid killing it unless it would prevent the current
12199 // application from running. By default we put the process in
12200 // with the rest of the background processes; as we scan through
12201 // its services we may bump it up from there.
12202 if (adj > hiddenAdj) {
12203 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012204 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012205 app.adjType = "bg-services";
12206 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012207 }
12208
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012209 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12210 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012211 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012212 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12213 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012214 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012215 if (cpr.clients.size() != 0) {
12216 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12217 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12218 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012219 if (client == app) {
12220 // Being our own client is not interesting.
12221 continue;
12222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012223 int myHiddenAdj = hiddenAdj;
12224 if (myHiddenAdj > client.hiddenAdj) {
12225 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12226 myHiddenAdj = client.hiddenAdj;
12227 } else {
12228 myHiddenAdj = FOREGROUND_APP_ADJ;
12229 }
12230 }
12231 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012232 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012233 if (adj > clientAdj) {
12234 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012235 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012236 if (!client.hidden) {
12237 app.hidden = false;
12238 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012239 if (client.keeping) {
12240 app.keeping = true;
12241 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012242 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012243 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12244 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012245 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012246 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012247 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012248 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12249 schedGroup = Process.THREAD_GROUP_DEFAULT;
12250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012251 }
12252 }
12253 // If the provider has external (non-framework) process
12254 // dependencies, ensure that its adjustment is at least
12255 // FOREGROUND_APP_ADJ.
12256 if (cpr.externals != 0) {
12257 if (adj > FOREGROUND_APP_ADJ) {
12258 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012259 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012260 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012261 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012262 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012263 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012264 }
12265 }
12266 }
12267 }
12268
12269 app.curRawAdj = adj;
12270
Joe Onorato8a9b2202010-02-26 18:56:32 -080012271 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012272 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12273 if (adj > app.maxAdj) {
12274 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012275 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012276 schedGroup = Process.THREAD_GROUP_DEFAULT;
12277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012278 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012279 if (adj < HIDDEN_APP_MIN_ADJ) {
12280 app.keeping = true;
12281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012282
12283 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012284 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012286 return adj;
12287 }
12288
12289 /**
12290 * Ask a given process to GC right now.
12291 */
12292 final void performAppGcLocked(ProcessRecord app) {
12293 try {
12294 app.lastRequestedGc = SystemClock.uptimeMillis();
12295 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012296 if (app.reportLowMemory) {
12297 app.reportLowMemory = false;
12298 app.thread.scheduleLowMemory();
12299 } else {
12300 app.thread.processInBackground();
12301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012302 }
12303 } catch (Exception e) {
12304 // whatever.
12305 }
12306 }
12307
12308 /**
12309 * Returns true if things are idle enough to perform GCs.
12310 */
Josh Bartel7f208742010-02-25 11:01:44 -060012311 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012312 return mParallelBroadcasts.size() == 0
12313 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012314 && (mSleeping || (mMainStack.mResumedActivity != null &&
12315 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012316 }
12317
12318 /**
12319 * Perform GCs on all processes that are waiting for it, but only
12320 * if things are idle.
12321 */
12322 final void performAppGcsLocked() {
12323 final int N = mProcessesToGc.size();
12324 if (N <= 0) {
12325 return;
12326 }
Josh Bartel7f208742010-02-25 11:01:44 -060012327 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012328 while (mProcessesToGc.size() > 0) {
12329 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012330 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012331 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12332 <= SystemClock.uptimeMillis()) {
12333 // To avoid spamming the system, we will GC processes one
12334 // at a time, waiting a few seconds between each.
12335 performAppGcLocked(proc);
12336 scheduleAppGcsLocked();
12337 return;
12338 } else {
12339 // It hasn't been long enough since we last GCed this
12340 // process... put it in the list to wait for its time.
12341 addProcessToGcListLocked(proc);
12342 break;
12343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012344 }
12345 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012346
12347 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012348 }
12349 }
12350
12351 /**
12352 * If all looks good, perform GCs on all processes waiting for them.
12353 */
12354 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012355 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012356 performAppGcsLocked();
12357 return;
12358 }
12359 // Still not idle, wait some more.
12360 scheduleAppGcsLocked();
12361 }
12362
12363 /**
12364 * Schedule the execution of all pending app GCs.
12365 */
12366 final void scheduleAppGcsLocked() {
12367 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012368
12369 if (mProcessesToGc.size() > 0) {
12370 // Schedule a GC for the time to the next process.
12371 ProcessRecord proc = mProcessesToGc.get(0);
12372 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12373
12374 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12375 long now = SystemClock.uptimeMillis();
12376 if (when < (now+GC_TIMEOUT)) {
12377 when = now + GC_TIMEOUT;
12378 }
12379 mHandler.sendMessageAtTime(msg, when);
12380 }
12381 }
12382
12383 /**
12384 * Add a process to the array of processes waiting to be GCed. Keeps the
12385 * list in sorted order by the last GC time. The process can't already be
12386 * on the list.
12387 */
12388 final void addProcessToGcListLocked(ProcessRecord proc) {
12389 boolean added = false;
12390 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12391 if (mProcessesToGc.get(i).lastRequestedGc <
12392 proc.lastRequestedGc) {
12393 added = true;
12394 mProcessesToGc.add(i+1, proc);
12395 break;
12396 }
12397 }
12398 if (!added) {
12399 mProcessesToGc.add(0, proc);
12400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012401 }
12402
12403 /**
12404 * Set up to ask a process to GC itself. This will either do it
12405 * immediately, or put it on the list of processes to gc the next
12406 * time things are idle.
12407 */
12408 final void scheduleAppGcLocked(ProcessRecord app) {
12409 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012410 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012411 return;
12412 }
12413 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012414 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012415 scheduleAppGcsLocked();
12416 }
12417 }
12418
Dianne Hackborn287952c2010-09-22 22:34:31 -070012419 final void checkExcessivePowerUsageLocked(boolean doKills) {
12420 updateCpuStatsNow();
12421
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012422 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012423 boolean doWakeKills = doKills;
12424 boolean doCpuKills = doKills;
12425 if (mLastPowerCheckRealtime == 0) {
12426 doWakeKills = false;
12427 }
12428 if (mLastPowerCheckUptime == 0) {
12429 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012430 }
12431 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012432 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012433 }
12434 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012435 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12436 final long curUptime = SystemClock.uptimeMillis();
12437 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12438 mLastPowerCheckRealtime = curRealtime;
12439 mLastPowerCheckUptime = curUptime;
12440 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12441 doWakeKills = false;
12442 }
12443 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12444 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012445 }
12446 int i = mLruProcesses.size();
12447 while (i > 0) {
12448 i--;
12449 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012450 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012451 long wtime;
12452 synchronized (stats) {
12453 wtime = stats.getProcessWakeTime(app.info.uid,
12454 app.pid, curRealtime);
12455 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012456 long wtimeUsed = wtime - app.lastWakeTime;
12457 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12458 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012459 StringBuilder sb = new StringBuilder(128);
12460 sb.append("Wake for ");
12461 app.toShortString(sb);
12462 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012463 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012464 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012465 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012466 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012467 sb.append((wtimeUsed*100)/realtimeSince);
12468 sb.append("%)");
12469 Slog.i(TAG, sb.toString());
12470 sb.setLength(0);
12471 sb.append("CPU for ");
12472 app.toShortString(sb);
12473 sb.append(": over ");
12474 TimeUtils.formatDuration(uptimeSince, sb);
12475 sb.append(" used ");
12476 TimeUtils.formatDuration(cputimeUsed, sb);
12477 sb.append(" (");
12478 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012479 sb.append("%)");
12480 Slog.i(TAG, sb.toString());
12481 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012482 // If a process has held a wake lock for more
12483 // than 50% of the time during this period,
12484 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012485 if (doWakeKills && realtimeSince > 0
12486 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12487 synchronized (stats) {
12488 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12489 realtimeSince, wtimeUsed);
12490 }
12491 Slog.w(TAG, "Excessive wake lock in " + app.processName
12492 + " (pid " + app.pid + "): held " + wtimeUsed
12493 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012494 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12495 app.processName, app.setAdj, "excessive wake lock");
12496 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012497 } else if (doCpuKills && uptimeSince > 0
12498 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12499 synchronized (stats) {
12500 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12501 uptimeSince, cputimeUsed);
12502 }
12503 Slog.w(TAG, "Excessive CPU in " + app.processName
12504 + " (pid " + app.pid + "): used " + cputimeUsed
12505 + " during " + uptimeSince);
12506 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12507 app.processName, app.setAdj, "excessive cpu");
12508 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012509 } else {
12510 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012511 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012512 }
12513 }
12514 }
12515 }
12516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012517 private final boolean updateOomAdjLocked(
12518 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12519 app.hiddenAdj = hiddenAdj;
12520
12521 if (app.thread == null) {
12522 return true;
12523 }
12524
Dianne Hackborn287952c2010-09-22 22:34:31 -070012525 final boolean wasKeeping = app.keeping;
12526
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012527 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012528
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012529 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012530 if (app.curRawAdj != app.setRawAdj) {
12531 if (app.curRawAdj > FOREGROUND_APP_ADJ
12532 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12533 // If this app is transitioning from foreground to
12534 // non-foreground, have it do a gc.
12535 scheduleAppGcLocked(app);
12536 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12537 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12538 // Likewise do a gc when an app is moving in to the
12539 // background (such as a service stopping).
12540 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012541 }
12542
12543 if (wasKeeping && !app.keeping) {
12544 // This app is no longer something we want to keep. Note
12545 // its current wake lock time to later know to kill it if
12546 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012547 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12548 synchronized (stats) {
12549 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12550 app.pid, SystemClock.elapsedRealtime());
12551 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012552 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012553 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012555 app.setRawAdj = app.curRawAdj;
12556 }
12557 if (adj != app.setAdj) {
12558 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012559 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012560 TAG, "Set app " + app.processName +
12561 " oom adj to " + adj);
12562 app.setAdj = adj;
12563 } else {
12564 return false;
12565 }
12566 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012567 if (app.setSchedGroup != app.curSchedGroup) {
12568 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012569 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012570 "Setting process group of " + app.processName
12571 + " to " + app.curSchedGroup);
12572 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012573 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012574 try {
12575 Process.setProcessGroup(app.pid, app.curSchedGroup);
12576 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012577 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012578 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012579 e.printStackTrace();
12580 } finally {
12581 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012582 }
12583 }
12584 if (false) {
12585 if (app.thread != null) {
12586 try {
12587 app.thread.setSchedulingGroup(app.curSchedGroup);
12588 } catch (RemoteException e) {
12589 }
12590 }
12591 }
12592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012593 }
12594
12595 return true;
12596 }
12597
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012598 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012599 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012600 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012601 resumedActivity = mMainStack.mPausingActivity;
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.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012604 }
12605 }
12606 return resumedActivity;
12607 }
12608
12609 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012610 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012611 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12612 int curAdj = app.curAdj;
12613 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12614 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12615
12616 mAdjSeq++;
12617
12618 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12619 if (res) {
12620 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12621 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12622 if (nowHidden != wasHidden) {
12623 // Changed to/from hidden state, so apps after it in the LRU
12624 // list may also be changed.
12625 updateOomAdjLocked();
12626 }
12627 }
12628 return res;
12629 }
12630
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012631 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012632 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012633 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012634 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12635
12636 if (false) {
12637 RuntimeException e = new RuntimeException();
12638 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012639 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012640 }
12641
12642 mAdjSeq++;
12643
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012644 // Let's determine how many processes we have running vs.
12645 // how many slots we have for background processes; we may want
12646 // to put multiple processes in a slot of there are enough of
12647 // them.
12648 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12649 int factor = (mLruProcesses.size()-4)/numSlots;
12650 if (factor < 1) factor = 1;
12651 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012652 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012654 // First try updating the OOM adjustment for each of the
12655 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012656 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012657 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12658 while (i > 0) {
12659 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012660 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012661 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012662 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012663 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012664 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012665 step++;
12666 if (step >= factor) {
12667 step = 0;
12668 curHiddenAdj++;
12669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012670 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012671 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012672 if (!app.killedBackground) {
12673 numHidden++;
12674 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012675 Slog.i(TAG, "No longer want " + app.processName
12676 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012677 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12678 app.processName, app.setAdj, "too many background");
12679 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012680 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012681 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012682 }
12683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012684 } else {
12685 didOomAdj = false;
12686 }
12687 }
12688
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012689 // If we return false, we will fall back on killing processes to
12690 // have a fixed limit. Do this if a limit has been requested; else
12691 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012692 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12693 }
12694
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012695 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012696 synchronized (this) {
12697 int i;
12698
12699 // First remove any unused application processes whose package
12700 // has been removed.
12701 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12702 final ProcessRecord app = mRemovedProcesses.get(i);
12703 if (app.activities.size() == 0
12704 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012705 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012706 TAG, "Exiting empty application process "
12707 + app.processName + " ("
12708 + (app.thread != null ? app.thread.asBinder() : null)
12709 + ")\n");
12710 if (app.pid > 0 && app.pid != MY_PID) {
12711 Process.killProcess(app.pid);
12712 } else {
12713 try {
12714 app.thread.scheduleExit();
12715 } catch (Exception e) {
12716 // Ignore exceptions.
12717 }
12718 }
12719 cleanUpApplicationRecordLocked(app, false, -1);
12720 mRemovedProcesses.remove(i);
12721
12722 if (app.persistent) {
12723 if (app.persistent) {
12724 addAppLocked(app.info);
12725 }
12726 }
12727 }
12728 }
12729
12730 // Now try updating the OOM adjustment for each of the
12731 // application processes based on their current state.
12732 // If the setOomAdj() API is not supported, then go with our
12733 // back-up plan...
12734 if (!updateOomAdjLocked()) {
12735
12736 // Count how many processes are running services.
12737 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012738 for (i=mLruProcesses.size()-1; i>=0; i--) {
12739 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012740
12741 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012742 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012743 // Don't count processes holding services against our
12744 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012745 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012746 TAG, "Not trimming app " + app + " with services: "
12747 + app.services);
12748 numServiceProcs++;
12749 }
12750 }
12751
12752 int curMaxProcs = mProcessLimit;
12753 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12754 if (mAlwaysFinishActivities) {
12755 curMaxProcs = 1;
12756 }
12757 curMaxProcs += numServiceProcs;
12758
12759 // Quit as many processes as we can to get down to the desired
12760 // process count. First remove any processes that no longer
12761 // have activites running in them.
12762 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012763 i<mLruProcesses.size()
12764 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012765 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012766 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012767 // Quit an application only if it is not currently
12768 // running any activities.
12769 if (!app.persistent && app.activities.size() == 0
12770 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012771 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012772 TAG, "Exiting empty application process "
12773 + app.processName + " ("
12774 + (app.thread != null ? app.thread.asBinder() : null)
12775 + ")\n");
12776 if (app.pid > 0 && app.pid != MY_PID) {
12777 Process.killProcess(app.pid);
12778 } else {
12779 try {
12780 app.thread.scheduleExit();
12781 } catch (Exception e) {
12782 // Ignore exceptions.
12783 }
12784 }
12785 // todo: For now we assume the application is not buggy
12786 // or evil, and will quit as a result of our request.
12787 // Eventually we need to drive this off of the death
12788 // notification, and kill the process if it takes too long.
12789 cleanUpApplicationRecordLocked(app, false, i);
12790 i--;
12791 }
12792 }
12793
12794 // If we still have too many processes, now from the least
12795 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012796 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012797 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012798 " of " + curMaxProcs + " processes");
12799 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012800 i<mLruProcesses.size()
12801 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012802 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012803 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012804 // Quit the application only if we have a state saved for
12805 // all of its activities.
12806 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012807 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012808 int NUMA = app.activities.size();
12809 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012810 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012811 TAG, "Looking to quit " + app.processName);
12812 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012813 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012814 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012815 TAG, " " + r.intent.getComponent().flattenToShortString()
12816 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12817 canQuit = (r.haveState || !r.stateNotNeeded)
12818 && !r.visible && r.stopped;
12819 }
12820 if (canQuit) {
12821 // Finish all of the activities, and then the app itself.
12822 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012823 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012824 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012825 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012826 }
12827 r.resultTo = null;
12828 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012829 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012830 + app.processName + " ("
12831 + (app.thread != null ? app.thread.asBinder() : null)
12832 + ")\n");
12833 if (app.pid > 0 && app.pid != MY_PID) {
12834 Process.killProcess(app.pid);
12835 } else {
12836 try {
12837 app.thread.scheduleExit();
12838 } catch (Exception e) {
12839 // Ignore exceptions.
12840 }
12841 }
12842 // todo: For now we assume the application is not buggy
12843 // or evil, and will quit as a result of our request.
12844 // Eventually we need to drive this off of the death
12845 // notification, and kill the process if it takes too long.
12846 cleanUpApplicationRecordLocked(app, false, i);
12847 i--;
12848 //dump();
12849 }
12850 }
12851
12852 }
12853
12854 int curMaxActivities = MAX_ACTIVITIES;
12855 if (mAlwaysFinishActivities) {
12856 curMaxActivities = 1;
12857 }
12858
12859 // Finally, if there are too many activities now running, try to
12860 // finish as many as we can to get back down to the limit.
12861 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012862 i<mMainStack.mLRUActivities.size()
12863 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012864 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012865 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012866 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012867
12868 // We can finish this one if we have its icicle saved and
12869 // it is not persistent.
12870 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012871 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012872 final int origSize = mMainStack.mLRUActivities.size();
12873 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012874
12875 // This will remove it from the LRU list, so keep
12876 // our index at the same value. Note that this check to
12877 // see if the size changes is just paranoia -- if
12878 // something unexpected happens, we don't want to end up
12879 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012880 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012881 i--;
12882 }
12883 }
12884 }
12885 }
12886 }
12887
12888 /** This method sends the specified signal to each of the persistent apps */
12889 public void signalPersistentProcesses(int sig) throws RemoteException {
12890 if (sig != Process.SIGNAL_USR1) {
12891 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12892 }
12893
12894 synchronized (this) {
12895 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12896 != PackageManager.PERMISSION_GRANTED) {
12897 throw new SecurityException("Requires permission "
12898 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12899 }
12900
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012901 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12902 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012903 if (r.thread != null && r.persistent) {
12904 Process.sendSignal(r.pid, sig);
12905 }
12906 }
12907 }
12908 }
12909
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012910 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012911 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012912
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012913 try {
12914 synchronized (this) {
12915 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12916 // its own permission.
12917 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12918 != PackageManager.PERMISSION_GRANTED) {
12919 throw new SecurityException("Requires permission "
12920 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012921 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012922
12923 if (start && fd == null) {
12924 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012925 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012926
12927 ProcessRecord proc = null;
12928 try {
12929 int pid = Integer.parseInt(process);
12930 synchronized (mPidsSelfLocked) {
12931 proc = mPidsSelfLocked.get(pid);
12932 }
12933 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012934 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012935
12936 if (proc == null) {
12937 HashMap<String, SparseArray<ProcessRecord>> all
12938 = mProcessNames.getMap();
12939 SparseArray<ProcessRecord> procs = all.get(process);
12940 if (procs != null && procs.size() > 0) {
12941 proc = procs.valueAt(0);
12942 }
12943 }
12944
12945 if (proc == null || proc.thread == null) {
12946 throw new IllegalArgumentException("Unknown process: " + process);
12947 }
12948
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080012949 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
12950 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012951 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12952 throw new SecurityException("Process not debuggable: " + proc);
12953 }
12954 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012955
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012956 proc.thread.profilerControl(start, path, fd);
12957 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012958 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012959 }
12960 } catch (RemoteException e) {
12961 throw new IllegalStateException("Process disappeared");
12962 } finally {
12963 if (fd != null) {
12964 try {
12965 fd.close();
12966 } catch (IOException e) {
12967 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012968 }
12969 }
12970 }
Andy McFadden824c5102010-07-09 16:26:57 -070012971
12972 public boolean dumpHeap(String process, boolean managed,
12973 String path, ParcelFileDescriptor fd) throws RemoteException {
12974
12975 try {
12976 synchronized (this) {
12977 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12978 // its own permission (same as profileControl).
12979 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12980 != PackageManager.PERMISSION_GRANTED) {
12981 throw new SecurityException("Requires permission "
12982 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12983 }
12984
12985 if (fd == null) {
12986 throw new IllegalArgumentException("null fd");
12987 }
12988
12989 ProcessRecord proc = null;
12990 try {
12991 int pid = Integer.parseInt(process);
12992 synchronized (mPidsSelfLocked) {
12993 proc = mPidsSelfLocked.get(pid);
12994 }
12995 } catch (NumberFormatException e) {
12996 }
12997
12998 if (proc == null) {
12999 HashMap<String, SparseArray<ProcessRecord>> all
13000 = mProcessNames.getMap();
13001 SparseArray<ProcessRecord> procs = all.get(process);
13002 if (procs != null && procs.size() > 0) {
13003 proc = procs.valueAt(0);
13004 }
13005 }
13006
13007 if (proc == null || proc.thread == null) {
13008 throw new IllegalArgumentException("Unknown process: " + process);
13009 }
13010
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013011 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13012 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013013 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13014 throw new SecurityException("Process not debuggable: " + proc);
13015 }
13016 }
13017
13018 proc.thread.dumpHeap(managed, path, fd);
13019 fd = null;
13020 return true;
13021 }
13022 } catch (RemoteException e) {
13023 throw new IllegalStateException("Process disappeared");
13024 } finally {
13025 if (fd != null) {
13026 try {
13027 fd.close();
13028 } catch (IOException e) {
13029 }
13030 }
13031 }
13032 }
13033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013034 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13035 public void monitor() {
13036 synchronized (this) { }
13037 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013038
13039 public void onCoreSettingsChange(Bundle settings) {
13040 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13041 ProcessRecord processRecord = mLruProcesses.get(i);
13042 try {
13043 if (processRecord.thread != null) {
13044 processRecord.thread.setCoreSettings(settings);
13045 }
13046 } catch (RemoteException re) {
13047 /* ignore */
13048 }
13049 }
13050 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013051}