blob: 1a10cffe15cedf37ff55d261fde10ab871a56020 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020058import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.Intent;
60import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070061import android.content.IIntentReceiver;
62import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070063import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.pm.ActivityInfo;
65import android.content.pm.ApplicationInfo;
66import android.content.pm.ConfigurationInfo;
67import android.content.pm.IPackageDataObserver;
68import android.content.pm.IPackageManager;
69import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080070import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070072import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.ProviderInfo;
74import android.content.pm.ResolveInfo;
75import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070076import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.content.res.Configuration;
78import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070079import android.net.Proxy;
80import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.net.Uri;
82import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080084import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070085import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080088import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.os.FileUtils;
90import android.os.Handler;
91import android.os.IBinder;
92import android.os.IPermissionController;
93import android.os.Looper;
94import android.os.Message;
95import android.os.Parcel;
96import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070098import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.RemoteException;
100import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700101import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.SystemClock;
103import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.util.Config;
106import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800107import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800108import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.util.PrintWriterPrinter;
110import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700111import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import android.view.Gravity;
113import android.view.LayoutInflater;
114import android.view.View;
115import android.view.WindowManager;
116import android.view.WindowManagerPolicy;
117
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700118import java.io.BufferedInputStream;
119import java.io.BufferedOutputStream;
120import java.io.DataInputStream;
121import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122import java.io.File;
123import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700126import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200127import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800128import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.io.PrintWriter;
130import java.lang.IllegalStateException;
131import java.lang.ref.WeakReference;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700132import java.net.InetSocketAddress;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700134import java.util.Collections;
135import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136import java.util.HashMap;
137import java.util.HashSet;
138import java.util.Iterator;
139import java.util.List;
140import java.util.Locale;
141import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700142import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700143import java.util.concurrent.atomic.AtomicBoolean;
144import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700146public final class ActivityManagerService extends ActivityManagerNative
147 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 static final String TAG = "ActivityManager";
149 static final boolean DEBUG = false;
150 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
151 static final boolean DEBUG_SWITCH = localLOGV || false;
152 static final boolean DEBUG_TASKS = localLOGV || false;
153 static final boolean DEBUG_PAUSE = localLOGV || false;
154 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
155 static final boolean DEBUG_TRANSITION = localLOGV || false;
156 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700157 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700159 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 static final boolean DEBUG_VISBILITY = localLOGV || false;
161 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700162 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800163 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700165 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700166 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700167 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700168 static final boolean DEBUG_POWER = localLOGV || false;
169 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 static final boolean VALIDATE_TOKENS = false;
171 static final boolean SHOW_ACTIVITY_START_TIME = true;
172
173 // Control over CPU and battery monitoring.
174 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
175 static final boolean MONITOR_CPU_USAGE = true;
176 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
177 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
178 static final boolean MONITOR_THREAD_CPU_USAGE = false;
179
Dianne Hackborn1655be42009-05-08 14:29:01 -0700180 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700181 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 private static final String SYSTEM_SECURE = "ro.secure";
184
185 // This is the maximum number of application processes we would like
186 // to have running. Due to the asynchronous nature of things, we can
187 // temporarily go beyond this limit.
188 static final int MAX_PROCESSES = 2;
189
190 // Set to false to leave processes running indefinitely, relying on
191 // the kernel killing them as resources are required.
192 static final boolean ENFORCE_PROCESS_LIMIT = false;
193
194 // This is the maximum number of activities that we would like to have
195 // running at a given time.
196 static final int MAX_ACTIVITIES = 20;
197
198 // Maximum number of recent tasks that we can remember.
199 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700200
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700201 // Amount of time after a call to stopAppSwitches() during which we will
202 // prevent further untrusted switches from happening.
203 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204
205 // How long we wait for a launched process to attach to the activity manager
206 // before we decide it's never going to come up for real.
207 static final int PROC_START_TIMEOUT = 10*1000;
208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 // How long to wait after going idle before forcing apps to GC.
210 static final int GC_TIMEOUT = 5*1000;
211
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700212 // The minimum amount of time between successive GC requests for a process.
213 static final int GC_MIN_INTERVAL = 60*1000;
214
Dianne Hackborn287952c2010-09-22 22:34:31 -0700215 // The rate at which we check for apps using excessive power -- 15 mins.
216 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
217
218 // The minimum sample duration we will allow before deciding we have
219 // enough data on wake locks to start killing things.
220 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
221
222 // The minimum sample duration we will allow before deciding we have
223 // enough data on CPU usage to start killing things.
224 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 // How long we allow a receiver to run before giving up on it.
227 static final int BROADCAST_TIMEOUT = 10*1000;
228
229 // How long we wait for a service to finish executing.
230 static final int SERVICE_TIMEOUT = 20*1000;
231
232 // How long a service needs to be running until restarting its process
233 // is no longer considered to be a relaunch of the service.
234 static final int SERVICE_RESTART_DURATION = 5*1000;
235
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700236 // How long a service needs to be running until it will start back at
237 // SERVICE_RESTART_DURATION after being killed.
238 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
239
240 // Multiplying factor to increase restart duration time by, for each time
241 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
242 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
243
244 // The minimum amount of time between restarting services that we allow.
245 // That is, when multiple services are restarting, we won't allow each
246 // to restart less than this amount of time from the last one.
247 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 // Maximum amount of time for there to be no activity on a service before
250 // we consider it non-essential and allow its process to go on the
251 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700252 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253
254 // How long we wait until we timeout on key dispatching.
255 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
256
257 // The minimum time we allow between crashes, for us to consider this
258 // application to be bad and stop and its services and reject broadcasts.
259 static final int MIN_CRASH_INTERVAL = 60*1000;
260
261 // How long we wait until we timeout on key dispatching during instrumentation.
262 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
263
264 // OOM adjustments for processes in various states:
265
266 // This is a process without anything currently running in it. Definitely
267 // the first to go! Value set in system/rootdir/init.rc on startup.
268 // This value is initalized in the constructor, careful when refering to
269 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800270 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271
272 // This is a process only hosting activities that are not visible,
273 // so it can be killed without any disruption. Value set in
274 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 static int HIDDEN_APP_MIN_ADJ;
277
The Android Open Source Project4df24232009-03-05 14:34:35 -0800278 // This is a process holding the home application -- we want to try
279 // avoiding killing it, even if it would normally be in the background,
280 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800281 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800282
Christopher Tate6fa95972009-06-05 18:43:55 -0700283 // This is a process currently hosting a backup operation. Killing it
284 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800285 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 // This is a process holding a secondary server -- killing it will not
288 // have much of an impact as far as the user is concerned. Value set in
289 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800290 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700292 // This is a process with a heavy-weight application. It is in the
293 // background, but we want to try to avoid killing it. Value set in
294 // system/rootdir/init.rc on startup.
295 static final int HEAVY_WEIGHT_APP_ADJ;
296
297 // This is a process only hosting components that are perceptible to the
298 // user, and we really want to avoid killing them, but they are not
299 // immediately visible. An example is background music playback. Value set in
300 // system/rootdir/init.rc on startup.
301 static final int PERCEPTIBLE_APP_ADJ;
302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 // This is a process only hosting activities that are visible to the
304 // user, so we'd prefer they don't disappear. Value set in
305 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307
308 // This is the process running the current foreground app. We'd really
309 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800310 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311
312 // This is a process running a core server, such as telephony. Definitely
313 // don't want to kill it, but doing so is not completely fatal.
314 static final int CORE_SERVER_ADJ = -12;
315
316 // The system process runs at the default adjustment.
317 static final int SYSTEM_ADJ = -16;
318
319 // Memory pages are 4K.
320 static final int PAGE_SIZE = 4*1024;
321
322 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800323 static final int EMPTY_APP_MEM;
324 static final int HIDDEN_APP_MEM;
325 static final int HOME_APP_MEM;
326 static final int BACKUP_APP_MEM;
327 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700328 static final int HEAVY_WEIGHT_APP_MEM;
329 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800330 static final int VISIBLE_APP_MEM;
331 static final int FOREGROUND_APP_MEM;
332
333 // The minimum number of hidden apps we want to be able to keep around,
334 // without empty apps being able to push them out of memory.
335 static final int MIN_HIDDEN_APPS = 2;
336
Dianne Hackborn8633e682010-04-22 16:03:41 -0700337 // The maximum number of hidden processes we will keep around before
338 // killing them; this is just a control to not let us go too crazy with
339 // keeping around processes on devices with large amounts of RAM.
340 static final int MAX_HIDDEN_APPS = 15;
341
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800342 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700343 // been idle for less than 15 seconds.
344 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800345
346 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700347 // been idle for less than 120 seconds.
348 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800349
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700350 static int getIntProp(String name, boolean allowZero) {
351 String str = SystemProperties.get(name);
352 if (str == null) {
353 throw new IllegalArgumentException("Property not defined: " + name);
354 }
355 int val = Integer.valueOf(str);
356 if (val == 0 && !allowZero) {
357 throw new IllegalArgumentException("Property must not be zero: " + name);
358 }
359 return val;
360 }
361
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800362 static {
363 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700364 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
365 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
366 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
367 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
368 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
369 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
370 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
371 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
372 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
373 // These days we use the last empty slot for hidden apps as well.
374 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
375 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
376 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
377 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
378 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
379 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
380 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
381 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
382 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
383 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385
Dan Egnor42471dd2010-01-07 17:25:22 -0800386 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387
388 static final String[] EMPTY_STRING_ARRAY = new String[0];
389
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700390 public ActivityStack mMainStack;
391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700393 * Description of a request to start a new activity, which has been held
394 * due to app switches being disabled.
395 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700396 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700397 ActivityRecord r;
398 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700399 Uri[] grantedUriPermissions;
400 int grantedMode;
401 boolean onlyIfNeeded;
402 }
403
404 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
405 = new ArrayList<PendingActivityLaunch>();
406
407 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * List of all active broadcasts that are to be executed immediately
409 * (without waiting for another broadcast to finish). Currently this only
410 * contains broadcasts to registered receivers, to avoid spinning up
411 * a bunch of processes to execute IntentReceiver components.
412 */
413 final ArrayList<BroadcastRecord> mParallelBroadcasts
414 = new ArrayList<BroadcastRecord>();
415
416 /**
417 * List of all active broadcasts that are to be executed one at a time.
418 * The object at the top of the list is the currently activity broadcasts;
419 * those after it are waiting for the top to finish..
420 */
421 final ArrayList<BroadcastRecord> mOrderedBroadcasts
422 = new ArrayList<BroadcastRecord>();
423
424 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800425 * Historical data of past broadcasts, for debugging.
426 */
427 static final int MAX_BROADCAST_HISTORY = 100;
428 final BroadcastRecord[] mBroadcastHistory
429 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
430
431 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 * Set when we current have a BROADCAST_INTENT_MSG in flight.
433 */
434 boolean mBroadcastsScheduled = false;
435
436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * Activity we have told the window manager to have key focus.
438 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700439 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700440 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 * List of intents that were used to start the most recent tasks.
442 */
443 final ArrayList<TaskRecord> mRecentTasks
444 = new ArrayList<TaskRecord>();
445
446 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 * All of the applications we currently have running organized by name.
448 * The keys are strings of the application package name (as
449 * returned by the package manager), and the keys are ApplicationRecord
450 * objects.
451 */
452 final ProcessMap<ProcessRecord> mProcessNames
453 = new ProcessMap<ProcessRecord>();
454
455 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700456 * The currently running heavy-weight process, if any.
457 */
458 ProcessRecord mHeavyWeightProcess = null;
459
460 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 * The last time that various processes have crashed.
462 */
463 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
464
465 /**
466 * Set of applications that we consider to be bad, and will reject
467 * incoming broadcasts from (which the user has no control over).
468 * Processes are added to this set when they have crashed twice within
469 * a minimum amount of time; they are removed from it when they are
470 * later restarted (hopefully due to some user action). The value is the
471 * time it was added to the list.
472 */
473 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
474
475 /**
476 * All of the processes we currently have running organized by pid.
477 * The keys are the pid running the application.
478 *
479 * <p>NOTE: This object is protected by its own lock, NOT the global
480 * activity manager lock!
481 */
482 final SparseArray<ProcessRecord> mPidsSelfLocked
483 = new SparseArray<ProcessRecord>();
484
485 /**
486 * All of the processes that have been forced to be foreground. The key
487 * is the pid of the caller who requested it (we hold a death
488 * link on it).
489 */
490 abstract class ForegroundToken implements IBinder.DeathRecipient {
491 int pid;
492 IBinder token;
493 }
494 final SparseArray<ForegroundToken> mForegroundProcesses
495 = new SparseArray<ForegroundToken>();
496
497 /**
498 * List of records for processes that someone had tried to start before the
499 * system was ready. We don't start them at that point, but ensure they
500 * are started by the time booting is complete.
501 */
502 final ArrayList<ProcessRecord> mProcessesOnHold
503 = new ArrayList<ProcessRecord>();
504
505 /**
506 * List of records for processes that we have started and are waiting
507 * for them to call back. This is really only needed when running in
508 * single processes mode, in which case we do not have a unique pid for
509 * each process.
510 */
511 final ArrayList<ProcessRecord> mStartingProcesses
512 = new ArrayList<ProcessRecord>();
513
514 /**
515 * List of persistent applications that are in the process
516 * of being started.
517 */
518 final ArrayList<ProcessRecord> mPersistentStartingProcesses
519 = new ArrayList<ProcessRecord>();
520
521 /**
522 * Processes that are being forcibly torn down.
523 */
524 final ArrayList<ProcessRecord> mRemovedProcesses
525 = new ArrayList<ProcessRecord>();
526
527 /**
528 * List of running applications, sorted by recent usage.
529 * The first entry in the list is the least recently used.
530 * It contains ApplicationRecord objects. This list does NOT include
531 * any persistent application records (since we never want to exit them).
532 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800533 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 = new ArrayList<ProcessRecord>();
535
536 /**
537 * List of processes that should gc as soon as things are idle.
538 */
539 final ArrayList<ProcessRecord> mProcessesToGc
540 = new ArrayList<ProcessRecord>();
541
542 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800543 * This is the process holding what we currently consider to be
544 * the "home" activity.
545 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700546 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800547
548 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 * Set of PendingResultRecord objects that are currently active.
550 */
551 final HashSet mPendingResultRecords = new HashSet();
552
553 /**
554 * Set of IntentSenderRecord objects that are currently active.
555 */
556 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
557 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
558
559 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800560 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700561 * already logged DropBox entries for. Guarded by itself. If
562 * something (rogue user app) forces this over
563 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
564 */
565 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
566 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
567
568 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700569 * Strict Mode background batched logging state.
570 *
571 * The string buffer is guarded by itself, and its lock is also
572 * used to determine if another batched write is already
573 * in-flight.
574 */
575 private final StringBuilder mStrictModeBuffer = new StringBuilder();
576
577 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700578 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
579 */
580 private boolean mPendingBroadcastTimeoutMessage;
581
582 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 * Intent broadcast that we have tried to start, but are
584 * waiting for its application's process to be created. We only
585 * need one (instead of a list) because we always process broadcasts
586 * one at a time, so no others can be started while waiting for this
587 * one.
588 */
589 BroadcastRecord mPendingBroadcast = null;
590
591 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700592 * The receiver index that is pending, to restart the broadcast if needed.
593 */
594 int mPendingBroadcastRecvIndex;
595
596 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 * Keeps track of all IIntentReceivers that have been registered for
598 * broadcasts. Hash keys are the receiver IBinder, hash value is
599 * a ReceiverList.
600 */
601 final HashMap mRegisteredReceivers = new HashMap();
602
603 /**
604 * Resolver for broadcast intents to registered receivers.
605 * Holds BroadcastFilter (subclass of IntentFilter).
606 */
607 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
608 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
609 @Override
610 protected boolean allowFilterResult(
611 BroadcastFilter filter, List<BroadcastFilter> dest) {
612 IBinder target = filter.receiverList.receiver.asBinder();
613 for (int i=dest.size()-1; i>=0; i--) {
614 if (dest.get(i).receiverList.receiver.asBinder() == target) {
615 return false;
616 }
617 }
618 return true;
619 }
620 };
621
622 /**
623 * State of all active sticky broadcasts. Keys are the action of the
624 * sticky Intent, values are an ArrayList of all broadcasted intents with
625 * that action (which should usually be one).
626 */
627 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
628 new HashMap<String, ArrayList<Intent>>();
629
630 /**
631 * All currently running services.
632 */
633 final HashMap<ComponentName, ServiceRecord> mServices =
634 new HashMap<ComponentName, ServiceRecord>();
635
636 /**
637 * All currently running services indexed by the Intent used to start them.
638 */
639 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
640 new HashMap<Intent.FilterComparison, ServiceRecord>();
641
642 /**
643 * All currently bound service connections. Keys are the IBinder of
644 * the client's IServiceConnection.
645 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700646 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
647 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648
649 /**
650 * List of services that we have been asked to start,
651 * but haven't yet been able to. It is used to hold start requests
652 * while waiting for their corresponding application thread to get
653 * going.
654 */
655 final ArrayList<ServiceRecord> mPendingServices
656 = new ArrayList<ServiceRecord>();
657
658 /**
659 * List of services that are scheduled to restart following a crash.
660 */
661 final ArrayList<ServiceRecord> mRestartingServices
662 = new ArrayList<ServiceRecord>();
663
664 /**
665 * List of services that are in the process of being stopped.
666 */
667 final ArrayList<ServiceRecord> mStoppingServices
668 = new ArrayList<ServiceRecord>();
669
670 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700671 * Backup/restore process management
672 */
673 String mBackupAppName = null;
674 BackupRecord mBackupTarget = null;
675
676 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677 * List of PendingThumbnailsRecord objects of clients who are still
678 * waiting to receive all of the thumbnails for a task.
679 */
680 final ArrayList mPendingThumbnails = new ArrayList();
681
682 /**
683 * List of HistoryRecord objects that have been finished and must
684 * still report back to a pending thumbnail receiver.
685 */
686 final ArrayList mCancelledThumbnails = new ArrayList();
687
688 /**
689 * All of the currently running global content providers. Keys are a
690 * string containing the provider name and values are a
691 * ContentProviderRecord object containing the data about it. Note
692 * that a single provider may be published under multiple names, so
693 * there may be multiple entries here for a single one in mProvidersByClass.
694 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700695 final HashMap<String, ContentProviderRecord> mProvidersByName
696 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697
698 /**
699 * All of the currently running global content providers. Keys are a
700 * string containing the provider's implementation class and values are a
701 * ContentProviderRecord object containing the data about it.
702 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700703 final HashMap<String, ContentProviderRecord> mProvidersByClass
704 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705
706 /**
707 * List of content providers who have clients waiting for them. The
708 * application is currently being launched and the provider will be
709 * removed from this list once it is published.
710 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700711 final ArrayList<ContentProviderRecord> mLaunchingProviders
712 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713
714 /**
715 * Global set of specific Uri permissions that have been granted.
716 */
717 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
718 = new SparseArray<HashMap<Uri, UriPermission>>();
719
720 /**
721 * Thread-local storage used to carry caller permissions over through
722 * indirect content-provider access.
723 * @see #ActivityManagerService.openContentUri()
724 */
725 private class Identity {
726 public int pid;
727 public int uid;
728
729 Identity(int _pid, int _uid) {
730 pid = _pid;
731 uid = _uid;
732 }
733 }
734 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
735
736 /**
737 * All information we have collected about the runtime performance of
738 * any user id that can impact battery performance.
739 */
740 final BatteryStatsService mBatteryStatsService;
741
742 /**
743 * information about component usage
744 */
745 final UsageStatsService mUsageStatsService;
746
747 /**
748 * Current configuration information. HistoryRecord objects are given
749 * a reference to this object to indicate which configuration they are
750 * currently running in, so this object must be kept immutable.
751 */
752 Configuration mConfiguration = new Configuration();
753
754 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800755 * Current sequencing integer of the configuration, for skipping old
756 * configurations.
757 */
758 int mConfigurationSeq = 0;
759
760 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700761 * Hardware-reported OpenGLES version.
762 */
763 final int GL_ES_VERSION;
764
765 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 * List of initialization arguments to pass to all processes when binding applications to them.
767 * For example, references to the commonly used services.
768 */
769 HashMap<String, IBinder> mAppBindArgs;
770
771 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700772 * Temporary to avoid allocations. Protected by main lock.
773 */
774 final StringBuilder mStringBuilder = new StringBuilder(256);
775
776 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 * Used to control how we initialize the service.
778 */
779 boolean mStartRunning = false;
780 ComponentName mTopComponent;
781 String mTopAction;
782 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700783 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 boolean mSystemReady = false;
785 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700786 boolean mWaitingUpdate = false;
787 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700788 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700789 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790
791 Context mContext;
792
793 int mFactoryTest;
794
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700795 boolean mCheckedForSetup;
796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700798 * The time at which we will allow normal application switches again,
799 * after a call to {@link #stopAppSwitches()}.
800 */
801 long mAppSwitchesAllowedTime;
802
803 /**
804 * This is set to true after the first switch after mAppSwitchesAllowedTime
805 * is set; any switches after that will clear the time.
806 */
807 boolean mDidAppSwitch;
808
809 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700810 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700811 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700812 long mLastPowerCheckRealtime;
813
814 /**
815 * Last time (in uptime) at which we checked for power usage.
816 */
817 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700818
819 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 * Set while we are wanting to sleep, to prevent any
821 * activities from being started/resumed.
822 */
823 boolean mSleeping = false;
824
825 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700826 * Set if we are shutting down the system, similar to sleeping.
827 */
828 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829
830 /**
831 * Task identifier that activities are currently being started
832 * in. Incremented each time a new task is created.
833 * todo: Replace this with a TokenSpace class that generates non-repeating
834 * integers that won't wrap.
835 */
836 int mCurTask = 1;
837
838 /**
839 * Current sequence id for oom_adj computation traversal.
840 */
841 int mAdjSeq = 0;
842
843 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700844 * Current sequence id for process LRU updating.
845 */
846 int mLruSeq = 0;
847
848 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
850 * is set, indicating the user wants processes started in such a way
851 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
852 * running in each process (thus no pre-initialized process, etc).
853 */
854 boolean mSimpleProcessManagement = false;
855
856 /**
857 * System monitoring: number of processes that died since the last
858 * N procs were started.
859 */
860 int[] mProcDeaths = new int[20];
861
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700862 /**
863 * This is set if we had to do a delayed dexopt of an app before launching
864 * it, to increasing the ANR timeouts in that case.
865 */
866 boolean mDidDexOpt;
867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 String mDebugApp = null;
869 boolean mWaitForDebugger = false;
870 boolean mDebugTransient = false;
871 String mOrigDebugApp = null;
872 boolean mOrigWaitForDebugger = false;
873 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700874 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700876 final RemoteCallbackList<IActivityWatcher> mWatchers
877 = new RemoteCallbackList<IActivityWatcher>();
878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 /**
880 * Callback of last caller to {@link #requestPss}.
881 */
882 Runnable mRequestPssCallback;
883
884 /**
885 * Remaining processes for which we are waiting results from the last
886 * call to {@link #requestPss}.
887 */
888 final ArrayList<ProcessRecord> mRequestPssList
889 = new ArrayList<ProcessRecord>();
890
891 /**
892 * Runtime statistics collection thread. This object's lock is used to
893 * protect all related state.
894 */
895 final Thread mProcessStatsThread;
896
897 /**
898 * Used to collect process stats when showing not responding dialog.
899 * Protected by mProcessStatsThread.
900 */
901 final ProcessStats mProcessStats = new ProcessStats(
902 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700903 final AtomicLong mLastCpuTime = new AtomicLong(0);
904 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 long mLastWriteTime = 0;
907
908 /**
909 * Set to true after the system has finished booting.
910 */
911 boolean mBooted = false;
912
913 int mProcessLimit = 0;
914
915 WindowManagerService mWindowManager;
916
917 static ActivityManagerService mSelf;
918 static ActivityThread mSystemThread;
919
920 private final class AppDeathRecipient implements IBinder.DeathRecipient {
921 final ProcessRecord mApp;
922 final int mPid;
923 final IApplicationThread mAppThread;
924
925 AppDeathRecipient(ProcessRecord app, int pid,
926 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800927 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 TAG, "New death recipient " + this
929 + " for thread " + thread.asBinder());
930 mApp = app;
931 mPid = pid;
932 mAppThread = thread;
933 }
934
935 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800936 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 TAG, "Death received in " + this
938 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 synchronized(ActivityManagerService.this) {
940 appDiedLocked(mApp, mPid, mAppThread);
941 }
942 }
943 }
944
945 static final int SHOW_ERROR_MSG = 1;
946 static final int SHOW_NOT_RESPONDING_MSG = 2;
947 static final int SHOW_FACTORY_ERROR_MSG = 3;
948 static final int UPDATE_CONFIGURATION_MSG = 4;
949 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
950 static final int WAIT_FOR_DEBUGGER_MSG = 6;
951 static final int BROADCAST_INTENT_MSG = 7;
952 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 static final int SERVICE_TIMEOUT_MSG = 12;
954 static final int UPDATE_TIME_ZONE = 13;
955 static final int SHOW_UID_ERROR_MSG = 14;
956 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700958 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700959 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800960 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700961 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
962 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700963 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700964 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700965 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700966 static final int UPDATE_HTTP_PROXY = 29;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967
968 AlertDialog mUidAlert;
969
970 final Handler mHandler = new Handler() {
971 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800972 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 //}
974
975 public void handleMessage(Message msg) {
976 switch (msg.what) {
977 case SHOW_ERROR_MSG: {
978 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 synchronized (ActivityManagerService.this) {
980 ProcessRecord proc = (ProcessRecord)data.get("app");
981 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800982 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 return;
984 }
985 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700986 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800987 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 d.show();
989 proc.crashDialog = d;
990 } else {
991 // The device is asleep, so just pretend that the user
992 // saw a crash dialog and hit "force quit".
993 res.set(0);
994 }
995 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700996
997 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 } break;
999 case SHOW_NOT_RESPONDING_MSG: {
1000 synchronized (ActivityManagerService.this) {
1001 HashMap data = (HashMap) msg.obj;
1002 ProcessRecord proc = (ProcessRecord)data.get("app");
1003 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001004 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 return;
1006 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001007
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001008 Intent intent = new Intent("android.intent.action.ANR");
1009 if (!mProcessesReady) {
1010 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1011 }
1012 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001013 null, null, 0, null, null, null,
1014 false, false, MY_PID, Process.SYSTEM_UID);
1015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001017 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 d.show();
1019 proc.anrDialog = d;
1020 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001021
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001022 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001024 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1025 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1026 synchronized (ActivityManagerService.this) {
1027 ProcessRecord proc = (ProcessRecord) data.get("app");
1028 if (proc == null) {
1029 Slog.e(TAG, "App not found when showing strict mode dialog.");
1030 break;
1031 }
1032 if (proc.crashDialog != null) {
1033 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1034 return;
1035 }
1036 AppErrorResult res = (AppErrorResult) data.get("result");
1037 if (!mSleeping && !mShuttingDown) {
1038 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1039 d.show();
1040 proc.crashDialog = d;
1041 } else {
1042 // The device is asleep, so just pretend that the user
1043 // saw a crash dialog and hit "force quit".
1044 res.set(0);
1045 }
1046 }
1047 ensureBootCompleted();
1048 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 case SHOW_FACTORY_ERROR_MSG: {
1050 Dialog d = new FactoryErrorDialog(
1051 mContext, msg.getData().getCharSequence("msg"));
1052 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001053 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 } break;
1055 case UPDATE_CONFIGURATION_MSG: {
1056 final ContentResolver resolver = mContext.getContentResolver();
1057 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1058 } break;
1059 case GC_BACKGROUND_PROCESSES_MSG: {
1060 synchronized (ActivityManagerService.this) {
1061 performAppGcsIfAppropriateLocked();
1062 }
1063 } break;
1064 case WAIT_FOR_DEBUGGER_MSG: {
1065 synchronized (ActivityManagerService.this) {
1066 ProcessRecord app = (ProcessRecord)msg.obj;
1067 if (msg.arg1 != 0) {
1068 if (!app.waitedForDebugger) {
1069 Dialog d = new AppWaitingForDebuggerDialog(
1070 ActivityManagerService.this,
1071 mContext, app);
1072 app.waitDialog = d;
1073 app.waitedForDebugger = true;
1074 d.show();
1075 }
1076 } else {
1077 if (app.waitDialog != null) {
1078 app.waitDialog.dismiss();
1079 app.waitDialog = null;
1080 }
1081 }
1082 }
1083 } break;
1084 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001085 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 TAG, "Received BROADCAST_INTENT_MSG");
1087 processNextBroadcast(true);
1088 } break;
1089 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001090 synchronized (ActivityManagerService.this) {
1091 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001095 if (mDidDexOpt) {
1096 mDidDexOpt = false;
1097 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1098 nmsg.obj = msg.obj;
1099 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1100 return;
1101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 serviceTimeout((ProcessRecord)msg.obj);
1103 } break;
1104 case UPDATE_TIME_ZONE: {
1105 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001106 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1107 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 if (r.thread != null) {
1109 try {
1110 r.thread.updateTimeZone();
1111 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001112 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 }
1114 }
1115 }
1116 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001117 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001118 case CLEAR_DNS_CACHE: {
1119 synchronized (ActivityManagerService.this) {
1120 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1121 ProcessRecord r = mLruProcesses.get(i);
1122 if (r.thread != null) {
1123 try {
1124 r.thread.clearDnsCache();
1125 } catch (RemoteException ex) {
1126 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1127 }
1128 }
1129 }
1130 }
1131 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001132 case UPDATE_HTTP_PROXY: {
1133 ProxyProperties proxy = (ProxyProperties)msg.obj;
1134 String host = "";
1135 String port = "";
1136 String exclList = "";
1137 if (proxy != null) {
1138 host = proxy.getHost();
1139 port = Integer.toString(proxy.getPort());
1140 exclList = proxy.getExclusionList();
1141 }
1142 synchronized (ActivityManagerService.this) {
1143 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1144 ProcessRecord r = mLruProcesses.get(i);
1145 if (r.thread != null) {
1146 try {
1147 r.thread.setHttpProxy(host, port, exclList);
1148 } catch (RemoteException ex) {
1149 Slog.w(TAG, "Failed to update http proxy for: " +
1150 r.info.processName);
1151 }
1152 }
1153 }
1154 }
1155 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 case SHOW_UID_ERROR_MSG: {
1157 // XXX This is a temporary dialog, no need to localize.
1158 AlertDialog d = new BaseErrorDialog(mContext);
1159 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1160 d.setCancelable(false);
1161 d.setTitle("System UIDs Inconsistent");
1162 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
Christian Mehlmauer7664e202010-07-20 08:46:17 +02001163 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1165 mUidAlert = d;
1166 d.show();
1167 } break;
1168 case IM_FEELING_LUCKY_MSG: {
1169 if (mUidAlert != null) {
1170 mUidAlert.dismiss();
1171 mUidAlert = null;
1172 }
1173 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001175 if (mDidDexOpt) {
1176 mDidDexOpt = false;
1177 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1178 nmsg.obj = msg.obj;
1179 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1180 return;
1181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 ProcessRecord app = (ProcessRecord)msg.obj;
1183 synchronized (ActivityManagerService.this) {
1184 processStartTimedOutLocked(app);
1185 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001186 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001187 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1188 synchronized (ActivityManagerService.this) {
1189 doPendingActivityLaunchesLocked(true);
1190 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001191 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001192 case KILL_APPLICATION_MSG: {
1193 synchronized (ActivityManagerService.this) {
1194 int uid = msg.arg1;
1195 boolean restart = (msg.arg2 == 1);
1196 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001197 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001198 }
1199 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001200 case FINALIZE_PENDING_INTENT_MSG: {
1201 ((PendingIntentRecord)msg.obj).completeFinalize();
1202 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001203 case POST_HEAVY_NOTIFICATION_MSG: {
1204 INotificationManager inm = NotificationManager.getService();
1205 if (inm == null) {
1206 return;
1207 }
1208
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001209 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001210 ProcessRecord process = root.app;
1211 if (process == null) {
1212 return;
1213 }
1214
1215 try {
1216 Context context = mContext.createPackageContext(process.info.packageName, 0);
1217 String text = mContext.getString(R.string.heavy_weight_notification,
1218 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1219 Notification notification = new Notification();
1220 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1221 notification.when = 0;
1222 notification.flags = Notification.FLAG_ONGOING_EVENT;
1223 notification.tickerText = text;
1224 notification.defaults = 0; // please be quiet
1225 notification.sound = null;
1226 notification.vibrate = null;
1227 notification.setLatestEventInfo(context, text,
1228 mContext.getText(R.string.heavy_weight_notification_detail),
1229 PendingIntent.getActivity(mContext, 0, root.intent,
1230 PendingIntent.FLAG_CANCEL_CURRENT));
1231
1232 try {
1233 int[] outId = new int[1];
1234 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1235 notification, outId);
1236 } catch (RuntimeException e) {
1237 Slog.w(ActivityManagerService.TAG,
1238 "Error showing notification for heavy-weight app", e);
1239 } catch (RemoteException e) {
1240 }
1241 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001242 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001243 }
1244 } break;
1245 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1246 INotificationManager inm = NotificationManager.getService();
1247 if (inm == null) {
1248 return;
1249 }
1250 try {
1251 inm.cancelNotification("android",
1252 R.string.heavy_weight_notification);
1253 } catch (RuntimeException e) {
1254 Slog.w(ActivityManagerService.TAG,
1255 "Error canceling notification for service", e);
1256 } catch (RemoteException e) {
1257 }
1258 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001259 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1260 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001261 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001262 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001263 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1264 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001265 }
1266 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 }
1268 }
1269 };
1270
1271 public static void setSystemProcess() {
1272 try {
1273 ActivityManagerService m = mSelf;
1274
1275 ServiceManager.addService("activity", m);
1276 ServiceManager.addService("meminfo", new MemBinder(m));
1277 if (MONITOR_CPU_USAGE) {
1278 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001280 ServiceManager.addService("permission", new PermissionController(m));
1281
1282 ApplicationInfo info =
1283 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001284 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001285 mSystemThread.installSystemApplicationInfo(info);
1286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 synchronized (mSelf) {
1288 ProcessRecord app = mSelf.newProcessRecordLocked(
1289 mSystemThread.getApplicationThread(), info,
1290 info.processName);
1291 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001292 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293 app.maxAdj = SYSTEM_ADJ;
1294 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1295 synchronized (mSelf.mPidsSelfLocked) {
1296 mSelf.mPidsSelfLocked.put(app.pid, app);
1297 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001298 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 }
1300 } catch (PackageManager.NameNotFoundException e) {
1301 throw new RuntimeException(
1302 "Unable to find android system package", e);
1303 }
1304 }
1305
1306 public void setWindowManager(WindowManagerService wm) {
1307 mWindowManager = wm;
1308 }
1309
1310 public static final Context main(int factoryTest) {
1311 AThread thr = new AThread();
1312 thr.start();
1313
1314 synchronized (thr) {
1315 while (thr.mService == null) {
1316 try {
1317 thr.wait();
1318 } catch (InterruptedException e) {
1319 }
1320 }
1321 }
1322
1323 ActivityManagerService m = thr.mService;
1324 mSelf = m;
1325 ActivityThread at = ActivityThread.systemMain();
1326 mSystemThread = at;
1327 Context context = at.getSystemContext();
1328 m.mContext = context;
1329 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001330 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331
1332 m.mBatteryStatsService.publish(context);
1333 m.mUsageStatsService.publish(context);
1334
1335 synchronized (thr) {
1336 thr.mReady = true;
1337 thr.notifyAll();
1338 }
1339
1340 m.startRunning(null, null, null, null);
1341
1342 return context;
1343 }
1344
1345 public static ActivityManagerService self() {
1346 return mSelf;
1347 }
1348
1349 static class AThread extends Thread {
1350 ActivityManagerService mService;
1351 boolean mReady = false;
1352
1353 public AThread() {
1354 super("ActivityManager");
1355 }
1356
1357 public void run() {
1358 Looper.prepare();
1359
1360 android.os.Process.setThreadPriority(
1361 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001362 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363
1364 ActivityManagerService m = new ActivityManagerService();
1365
1366 synchronized (this) {
1367 mService = m;
1368 notifyAll();
1369 }
1370
1371 synchronized (this) {
1372 while (!mReady) {
1373 try {
1374 wait();
1375 } catch (InterruptedException e) {
1376 }
1377 }
1378 }
1379
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001380 // For debug builds, log event loop stalls to dropbox for analysis.
1381 if (StrictMode.conditionallyEnableDebugLogging()) {
1382 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1383 }
1384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 Looper.loop();
1386 }
1387 }
1388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 static class MemBinder extends Binder {
1390 ActivityManagerService mActivityManagerService;
1391 MemBinder(ActivityManagerService activityManagerService) {
1392 mActivityManagerService = activityManagerService;
1393 }
1394
1395 @Override
1396 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1397 ActivityManagerService service = mActivityManagerService;
1398 ArrayList<ProcessRecord> procs;
1399 synchronized (mActivityManagerService) {
1400 if (args != null && args.length > 0
1401 && args[0].charAt(0) != '-') {
1402 procs = new ArrayList<ProcessRecord>();
1403 int pid = -1;
1404 try {
1405 pid = Integer.parseInt(args[0]);
1406 } catch (NumberFormatException e) {
1407
1408 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001409 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1410 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 if (proc.pid == pid) {
1412 procs.add(proc);
1413 } else if (proc.processName.equals(args[0])) {
1414 procs.add(proc);
1415 }
1416 }
1417 if (procs.size() <= 0) {
1418 pw.println("No process found for: " + args[0]);
1419 return;
1420 }
1421 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001422 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
1424 }
1425 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1426 }
1427 }
1428
1429 static class CpuBinder extends Binder {
1430 ActivityManagerService mActivityManagerService;
1431 CpuBinder(ActivityManagerService activityManagerService) {
1432 mActivityManagerService = activityManagerService;
1433 }
1434
1435 @Override
1436 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1437 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001438 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1439 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1440 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 }
1442 }
1443 }
1444
1445 private ActivityManagerService() {
1446 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1447 if (v != null && Integer.getInteger(v) != 0) {
1448 mSimpleProcessManagement = true;
1449 }
1450 v = System.getenv("ANDROID_DEBUG_APP");
1451 if (v != null) {
1452 mSimpleProcessManagement = true;
1453 }
1454
Joe Onorato8a9b2202010-02-26 18:56:32 -08001455 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 File dataDir = Environment.getDataDirectory();
1458 File systemDir = new File(dataDir, "system");
1459 systemDir.mkdirs();
1460 mBatteryStatsService = new BatteryStatsService(new File(
1461 systemDir, "batterystats.bin").toString());
1462 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001463 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001464 mOnBattery = DEBUG_POWER ? true
1465 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001466 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001468 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001469 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470
Jack Palevichb90d28c2009-07-22 15:35:24 -07001471 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1472 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1473
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001474 mConfiguration.setToDefaults();
1475 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 mProcessStats.init();
1477
1478 // Add ourself to the Watchdog monitors.
1479 Watchdog.getInstance().addMonitor(this);
1480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 mProcessStatsThread = new Thread("ProcessStats") {
1482 public void run() {
1483 while (true) {
1484 try {
1485 try {
1486 synchronized(this) {
1487 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001488 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001490 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 // + ", write delay=" + nextWriteDelay);
1492 if (nextWriteDelay < nextCpuDelay) {
1493 nextCpuDelay = nextWriteDelay;
1494 }
1495 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001496 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 this.wait(nextCpuDelay);
1498 }
1499 }
1500 } catch (InterruptedException e) {
1501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 updateCpuStatsNow();
1503 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001504 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 }
1506 }
1507 }
1508 };
1509 mProcessStatsThread.start();
1510 }
1511
1512 @Override
1513 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1514 throws RemoteException {
1515 try {
1516 return super.onTransact(code, data, reply, flags);
1517 } catch (RuntimeException e) {
1518 // The activity manager only throws security exceptions, so let's
1519 // log all others.
1520 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001521 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 }
1523 throw e;
1524 }
1525 }
1526
1527 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001528 final long now = SystemClock.uptimeMillis();
1529 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1530 return;
1531 }
1532 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1533 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 mProcessStatsThread.notify();
1535 }
1536 }
1537 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 void updateCpuStatsNow() {
1540 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001541 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 final long now = SystemClock.uptimeMillis();
1543 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001546 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1547 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 haveNewCpuStats = true;
1549 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001550 //Slog.i(TAG, mProcessStats.printCurrentState());
1551 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 // + mProcessStats.getTotalCpuPercent() + "%");
1553
Joe Onorato8a9b2202010-02-26 18:56:32 -08001554 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 if ("true".equals(SystemProperties.get("events.cpu"))) {
1556 int user = mProcessStats.getLastUserTime();
1557 int system = mProcessStats.getLastSystemTime();
1558 int iowait = mProcessStats.getLastIoWaitTime();
1559 int irq = mProcessStats.getLastIrqTime();
1560 int softIrq = mProcessStats.getLastSoftIrqTime();
1561 int idle = mProcessStats.getLastIdleTime();
1562
1563 int total = user + system + iowait + irq + softIrq + idle;
1564 if (total == 0) total = 1;
1565
Doug Zongker2bec3d42009-12-04 12:52:44 -08001566 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 ((user+system+iowait+irq+softIrq) * 100) / total,
1568 (user * 100) / total,
1569 (system * 100) / total,
1570 (iowait * 100) / total,
1571 (irq * 100) / total,
1572 (softIrq * 100) / total);
1573 }
1574 }
1575
Amith Yamasanie43530a2009-08-21 13:11:37 -07001576 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001577 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001578 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 synchronized(mPidsSelfLocked) {
1580 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001581 if (mOnBattery) {
1582 int perc = bstats.startAddingCpuLocked();
1583 int totalUTime = 0;
1584 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001585 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001587 ProcessStats.Stats st = mProcessStats.getStats(i);
1588 if (!st.working) {
1589 continue;
1590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001592 int otherUTime = (st.rel_utime*perc)/100;
1593 int otherSTime = (st.rel_stime*perc)/100;
1594 totalUTime += otherUTime;
1595 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 if (pr != null) {
1597 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001598 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1599 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001600 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001601 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001602 } else {
1603 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001604 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001605 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001606 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1607 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001608 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 }
1611 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001612 bstats.finishAddingCpuLocked(perc, totalUTime,
1613 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 }
1615 }
1616 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1619 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001620 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 }
1622 }
1623 }
1624 }
1625
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001626 @Override
1627 public void batteryNeedsCpuUpdate() {
1628 updateCpuStatsNow();
1629 }
1630
1631 @Override
1632 public void batteryPowerChanged(boolean onBattery) {
1633 // When plugging in, update the CPU stats first before changing
1634 // the plug state.
1635 updateCpuStatsNow();
1636 synchronized (this) {
1637 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001638 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001639 }
1640 }
1641 }
1642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 /**
1644 * Initialize the application bind args. These are passed to each
1645 * process when the bindApplication() IPC is sent to the process. They're
1646 * lazily setup to make sure the services are running when they're asked for.
1647 */
1648 private HashMap<String, IBinder> getCommonServicesLocked() {
1649 if (mAppBindArgs == null) {
1650 mAppBindArgs = new HashMap<String, IBinder>();
1651
1652 // Setup the application init args
1653 mAppBindArgs.put("package", ServiceManager.getService("package"));
1654 mAppBindArgs.put("window", ServiceManager.getService("window"));
1655 mAppBindArgs.put(Context.ALARM_SERVICE,
1656 ServiceManager.getService(Context.ALARM_SERVICE));
1657 }
1658 return mAppBindArgs;
1659 }
1660
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001661 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 if (mFocusedActivity != r) {
1663 mFocusedActivity = r;
1664 mWindowManager.setFocusedApp(r, true);
1665 }
1666 }
1667
Dianne Hackborn906497c2010-05-10 15:57:38 -07001668 private final void updateLruProcessInternalLocked(ProcessRecord app,
1669 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001671 int lrui = mLruProcesses.indexOf(app);
1672 if (lrui >= 0) mLruProcesses.remove(lrui);
1673
1674 int i = mLruProcesses.size()-1;
1675 int skipTop = 0;
1676
Dianne Hackborn906497c2010-05-10 15:57:38 -07001677 app.lruSeq = mLruSeq;
1678
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001679 // compute the new weight for this process.
1680 if (updateActivityTime) {
1681 app.lastActivityTime = SystemClock.uptimeMillis();
1682 }
1683 if (app.activities.size() > 0) {
1684 // If this process has activities, we more strongly want to keep
1685 // it around.
1686 app.lruWeight = app.lastActivityTime;
1687 } else if (app.pubProviders.size() > 0) {
1688 // If this process contains content providers, we want to keep
1689 // it a little more strongly.
1690 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1691 // Also don't let it kick out the first few "real" hidden processes.
1692 skipTop = MIN_HIDDEN_APPS;
1693 } else {
1694 // If this process doesn't have activities, we less strongly
1695 // want to keep it around, and generally want to avoid getting
1696 // in front of any very recently used activities.
1697 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1698 // Also don't let it kick out the first few "real" hidden processes.
1699 skipTop = MIN_HIDDEN_APPS;
1700 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001701
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001702 while (i >= 0) {
1703 ProcessRecord p = mLruProcesses.get(i);
1704 // If this app shouldn't be in front of the first N background
1705 // apps, then skip over that many that are currently hidden.
1706 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1707 skipTop--;
1708 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001709 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001710 mLruProcesses.add(i+1, app);
1711 break;
1712 }
1713 i--;
1714 }
1715 if (i < 0) {
1716 mLruProcesses.add(0, app);
1717 }
1718
Dianne Hackborn906497c2010-05-10 15:57:38 -07001719 // If the app is currently using a content provider or service,
1720 // bump those processes as well.
1721 if (app.connections.size() > 0) {
1722 for (ConnectionRecord cr : app.connections) {
1723 if (cr.binding != null && cr.binding.service != null
1724 && cr.binding.service.app != null
1725 && cr.binding.service.app.lruSeq != mLruSeq) {
1726 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1727 updateActivityTime, i+1);
1728 }
1729 }
1730 }
1731 if (app.conProviders.size() > 0) {
1732 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1733 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1734 updateLruProcessInternalLocked(cpr.app, oomAdj,
1735 updateActivityTime, i+1);
1736 }
1737 }
1738 }
1739
Joe Onorato8a9b2202010-02-26 18:56:32 -08001740 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 if (oomAdj) {
1742 updateOomAdjLocked();
1743 }
1744 }
1745
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001746 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001747 boolean oomAdj, boolean updateActivityTime) {
1748 mLruSeq++;
1749 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1750 }
1751
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001752 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 String processName, int uid) {
1754 if (uid == Process.SYSTEM_UID) {
1755 // The system gets to run in any process. If there are multiple
1756 // processes with the same uid, just pick the first (this
1757 // should never happen).
1758 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1759 processName);
1760 return procs != null ? procs.valueAt(0) : null;
1761 }
1762 ProcessRecord proc = mProcessNames.get(processName, uid);
1763 return proc;
1764 }
1765
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001766 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001767 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001768 try {
1769 if (pm.performDexOpt(packageName)) {
1770 mDidDexOpt = true;
1771 }
1772 } catch (RemoteException e) {
1773 }
1774 }
1775
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001776 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 int transit = mWindowManager.getPendingAppTransition();
1778 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1779 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1780 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1781 }
1782
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001783 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001785 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1787 // We don't have to do anything more if:
1788 // (1) There is an existing application record; and
1789 // (2) The caller doesn't think it is dead, OR there is no thread
1790 // object attached to it so we know it couldn't have crashed; and
1791 // (3) There is a pid assigned to it, so it is either starting or
1792 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001793 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 + " app=" + app + " knownToBeDead=" + knownToBeDead
1795 + " thread=" + (app != null ? app.thread : null)
1796 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001797 if (app != null && app.pid > 0) {
1798 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001799 // We already have the app running, or are waiting for it to
1800 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001801 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001802 return app;
1803 } else {
1804 // An application record is attached to a previous process,
1805 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001806 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001807 handleAppDiedLocked(app, true);
1808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 String hostingNameStr = hostingName != null
1812 ? hostingName.flattenToShortString() : null;
1813
1814 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1815 // If we are in the background, then check to see if this process
1816 // is bad. If so, we will just silently fail.
1817 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001818 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1819 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 return null;
1821 }
1822 } else {
1823 // When the user is explicitly starting a process, then clear its
1824 // crash count so that we won't make it bad until they see at
1825 // least one crash dialog again, and make the process good again
1826 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001827 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1828 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 mProcessCrashTimes.remove(info.processName, info.uid);
1830 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001831 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 info.processName);
1833 mBadProcesses.remove(info.processName, info.uid);
1834 if (app != null) {
1835 app.bad = false;
1836 }
1837 }
1838 }
1839
1840 if (app == null) {
1841 app = newProcessRecordLocked(null, info, processName);
1842 mProcessNames.put(processName, info.uid, app);
1843 } else {
1844 // If this is a new package in the process, add the package to the list
1845 app.addPackage(info.packageName);
1846 }
1847
1848 // If the system is not ready yet, then hold off on starting this
1849 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001850 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001851 && !isAllowedWhileBooting(info)
1852 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 if (!mProcessesOnHold.contains(app)) {
1854 mProcessesOnHold.add(app);
1855 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001856 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 return app;
1858 }
1859
1860 startProcessLocked(app, hostingType, hostingNameStr);
1861 return (app.pid != 0) ? app : null;
1862 }
1863
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001864 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1865 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1866 }
1867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 private final void startProcessLocked(ProcessRecord app,
1869 String hostingType, String hostingNameStr) {
1870 if (app.pid > 0 && app.pid != MY_PID) {
1871 synchronized (mPidsSelfLocked) {
1872 mPidsSelfLocked.remove(app.pid);
1873 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1874 }
1875 app.pid = 0;
1876 }
1877
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001878 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1879 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001880 mProcessesOnHold.remove(app);
1881
1882 updateCpuStats();
1883
1884 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1885 mProcDeaths[0] = 0;
1886
1887 try {
1888 int uid = app.info.uid;
1889 int[] gids = null;
1890 try {
1891 gids = mContext.getPackageManager().getPackageGids(
1892 app.info.packageName);
1893 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001894 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 }
1896 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1897 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1898 && mTopComponent != null
1899 && app.processName.equals(mTopComponent.getPackageName())) {
1900 uid = 0;
1901 }
1902 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1903 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1904 uid = 0;
1905 }
1906 }
1907 int debugFlags = 0;
1908 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1909 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1910 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001911 // Run the app in safe mode if its manifest requests so or the
1912 // system is booted in safe mode.
1913 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1914 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001915 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1918 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1919 }
1920 if ("1".equals(SystemProperties.get("debug.assert"))) {
1921 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1922 }
1923 int pid = Process.start("android.app.ActivityThread",
1924 mSimpleProcessManagement ? app.processName : null, uid, uid,
1925 gids, debugFlags, null);
1926 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1927 synchronized (bs) {
1928 if (bs.isOnBattery()) {
1929 app.batteryStats.incStartsLocked();
1930 }
1931 }
1932
Doug Zongker2bec3d42009-12-04 12:52:44 -08001933 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 app.processName, hostingType,
1935 hostingNameStr != null ? hostingNameStr : "");
1936
1937 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001938 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 }
1940
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001941 StringBuilder buf = mStringBuilder;
1942 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 buf.append("Start proc ");
1944 buf.append(app.processName);
1945 buf.append(" for ");
1946 buf.append(hostingType);
1947 if (hostingNameStr != null) {
1948 buf.append(" ");
1949 buf.append(hostingNameStr);
1950 }
1951 buf.append(": pid=");
1952 buf.append(pid);
1953 buf.append(" uid=");
1954 buf.append(uid);
1955 buf.append(" gids={");
1956 if (gids != null) {
1957 for (int gi=0; gi<gids.length; gi++) {
1958 if (gi != 0) buf.append(", ");
1959 buf.append(gids[gi]);
1960
1961 }
1962 }
1963 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001964 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 if (pid == 0 || pid == MY_PID) {
1966 // Processes are being emulated with threads.
1967 app.pid = MY_PID;
1968 app.removed = false;
1969 mStartingProcesses.add(app);
1970 } else if (pid > 0) {
1971 app.pid = pid;
1972 app.removed = false;
1973 synchronized (mPidsSelfLocked) {
1974 this.mPidsSelfLocked.put(pid, app);
1975 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1976 msg.obj = app;
1977 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1978 }
1979 } else {
1980 app.pid = 0;
1981 RuntimeException e = new RuntimeException(
1982 "Failure starting process " + app.processName
1983 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001984 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 }
1986 } catch (RuntimeException e) {
1987 // XXX do better error recovery.
1988 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001989 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 }
1991 }
1992
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001993 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001994 if (resumed) {
1995 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1996 } else {
1997 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1998 }
1999 }
2000
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002001 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002002 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2003 && mTopAction == null) {
2004 // We are running in factory test mode, but unable to find
2005 // the factory test app, so just sit around displaying the
2006 // error message and don't try to start anything.
2007 return false;
2008 }
2009 Intent intent = new Intent(
2010 mTopAction,
2011 mTopData != null ? Uri.parse(mTopData) : null);
2012 intent.setComponent(mTopComponent);
2013 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2014 intent.addCategory(Intent.CATEGORY_HOME);
2015 }
2016 ActivityInfo aInfo =
2017 intent.resolveActivityInfo(mContext.getPackageManager(),
2018 STOCK_PM_FLAGS);
2019 if (aInfo != null) {
2020 intent.setComponent(new ComponentName(
2021 aInfo.applicationInfo.packageName, aInfo.name));
2022 // Don't do this if the home app is currently being
2023 // instrumented.
2024 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2025 aInfo.applicationInfo.uid);
2026 if (app == null || app.instrumentationClass == null) {
2027 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002028 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002029 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002030 }
2031 }
2032
2033
2034 return true;
2035 }
2036
2037 /**
2038 * Starts the "new version setup screen" if appropriate.
2039 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002040 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002041 // Only do this once per boot.
2042 if (mCheckedForSetup) {
2043 return;
2044 }
2045
2046 // We will show this screen if the current one is a different
2047 // version than the last one shown, and we are not running in
2048 // low-level factory test mode.
2049 final ContentResolver resolver = mContext.getContentResolver();
2050 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2051 Settings.Secure.getInt(resolver,
2052 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2053 mCheckedForSetup = true;
2054
2055 // See if we should be showing the platform update setup UI.
2056 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2057 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2058 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2059
2060 // We don't allow third party apps to replace this.
2061 ResolveInfo ri = null;
2062 for (int i=0; ris != null && i<ris.size(); i++) {
2063 if ((ris.get(i).activityInfo.applicationInfo.flags
2064 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2065 ri = ris.get(i);
2066 break;
2067 }
2068 }
2069
2070 if (ri != null) {
2071 String vers = ri.activityInfo.metaData != null
2072 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2073 : null;
2074 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2075 vers = ri.activityInfo.applicationInfo.metaData.getString(
2076 Intent.METADATA_SETUP_VERSION);
2077 }
2078 String lastVers = Settings.Secure.getString(
2079 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2080 if (vers != null && !vers.equals(lastVers)) {
2081 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2082 intent.setComponent(new ComponentName(
2083 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002084 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002085 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002086 }
2087 }
2088 }
2089 }
2090
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002091 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002092 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002093
2094 final int identHash = System.identityHashCode(r);
2095 updateUsageStats(r, true);
2096
2097 int i = mWatchers.beginBroadcast();
2098 while (i > 0) {
2099 i--;
2100 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2101 if (w != null) {
2102 try {
2103 w.activityResuming(identHash);
2104 } catch (RemoteException e) {
2105 }
2106 }
2107 }
2108 mWatchers.finishBroadcast();
2109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002111 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002112 final int N = mPendingActivityLaunches.size();
2113 if (N <= 0) {
2114 return;
2115 }
2116 for (int i=0; i<N; i++) {
2117 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002118 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002119 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2120 doResume && i == (N-1));
2121 }
2122 mPendingActivityLaunches.clear();
2123 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002124
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002125 public final int startActivity(IApplicationThread caller,
2126 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2127 int grantedMode, IBinder resultTo,
2128 String resultWho, int requestCode, boolean onlyIfNeeded,
2129 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002130 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002131 grantedUriPermissions, grantedMode, resultTo, resultWho,
2132 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002133 }
2134
2135 public final WaitResult startActivityAndWait(IApplicationThread caller,
2136 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2137 int grantedMode, IBinder resultTo,
2138 String resultWho, int requestCode, boolean onlyIfNeeded,
2139 boolean debug) {
2140 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002141 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002142 grantedUriPermissions, grantedMode, resultTo, resultWho,
2143 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002144 return res;
2145 }
2146
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002147 public final int startActivityWithConfig(IApplicationThread caller,
2148 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2149 int grantedMode, IBinder resultTo,
2150 String resultWho, int requestCode, boolean onlyIfNeeded,
2151 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002152 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002153 grantedUriPermissions, grantedMode, resultTo, resultWho,
2154 requestCode, onlyIfNeeded, debug, null, config);
2155 }
2156
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002157 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002158 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002159 IBinder resultTo, String resultWho, int requestCode,
2160 int flagsMask, int flagsValues) {
2161 // Refuse possible leaked file descriptors
2162 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2163 throw new IllegalArgumentException("File descriptors passed in Intent");
2164 }
2165
2166 IIntentSender sender = intent.getTarget();
2167 if (!(sender instanceof PendingIntentRecord)) {
2168 throw new IllegalArgumentException("Bad PendingIntent object");
2169 }
2170
2171 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002172
2173 synchronized (this) {
2174 // If this is coming from the currently resumed activity, it is
2175 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002176 if (mMainStack.mResumedActivity != null
2177 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002178 Binder.getCallingUid()) {
2179 mAppSwitchesAllowedTime = 0;
2180 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002181 }
2182
2183 return pir.sendInner(0, fillInIntent, resolvedType,
2184 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2185 }
2186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187 public boolean startNextMatchingActivity(IBinder callingActivity,
2188 Intent intent) {
2189 // Refuse possible leaked file descriptors
2190 if (intent != null && intent.hasFileDescriptors() == true) {
2191 throw new IllegalArgumentException("File descriptors passed in Intent");
2192 }
2193
2194 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002195 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 if (index < 0) {
2197 return false;
2198 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002199 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 if (r.app == null || r.app.thread == null) {
2201 // The caller is not running... d'oh!
2202 return false;
2203 }
2204 intent = new Intent(intent);
2205 // The caller is not allowed to change the data.
2206 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2207 // And we are resetting to find the next component...
2208 intent.setComponent(null);
2209
2210 ActivityInfo aInfo = null;
2211 try {
2212 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002213 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002215 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216
2217 // Look for the original activity in the list...
2218 final int N = resolves != null ? resolves.size() : 0;
2219 for (int i=0; i<N; i++) {
2220 ResolveInfo rInfo = resolves.get(i);
2221 if (rInfo.activityInfo.packageName.equals(r.packageName)
2222 && rInfo.activityInfo.name.equals(r.info.name)) {
2223 // We found the current one... the next matching is
2224 // after it.
2225 i++;
2226 if (i<N) {
2227 aInfo = resolves.get(i).activityInfo;
2228 }
2229 break;
2230 }
2231 }
2232 } catch (RemoteException e) {
2233 }
2234
2235 if (aInfo == null) {
2236 // Nobody who is next!
2237 return false;
2238 }
2239
2240 intent.setComponent(new ComponentName(
2241 aInfo.applicationInfo.packageName, aInfo.name));
2242 intent.setFlags(intent.getFlags()&~(
2243 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2244 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2245 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2246 Intent.FLAG_ACTIVITY_NEW_TASK));
2247
2248 // Okay now we need to start the new activity, replacing the
2249 // currently running activity. This is a little tricky because
2250 // we want to start the new one as if the current one is finished,
2251 // but not finish the current one first so that there is no flicker.
2252 // And thus...
2253 final boolean wasFinishing = r.finishing;
2254 r.finishing = true;
2255
2256 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002257 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 final String resultWho = r.resultWho;
2259 final int requestCode = r.requestCode;
2260 r.resultTo = null;
2261 if (resultTo != null) {
2262 resultTo.removeResultsLocked(r, resultWho, requestCode);
2263 }
2264
2265 final long origId = Binder.clearCallingIdentity();
2266 // XXX we are not dealing with propagating grantedUriPermissions...
2267 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002268 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002270 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 Binder.restoreCallingIdentity(origId);
2272
2273 r.finishing = wasFinishing;
2274 if (res != START_SUCCESS) {
2275 return false;
2276 }
2277 return true;
2278 }
2279 }
2280
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002281 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 Intent intent, String resolvedType, IBinder resultTo,
2283 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002284
2285 // This is so super not safe, that only the system (or okay root)
2286 // can do it.
2287 final int callingUid = Binder.getCallingUid();
2288 if (callingUid != 0 && callingUid != Process.myUid()) {
2289 throw new SecurityException(
2290 "startActivityInPackage only available to the system");
2291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002293 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2294 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2295 }
2296
2297 public final int startActivities(IApplicationThread caller,
2298 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2299 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2300 }
2301
2302 public final int startActivitiesInPackage(int uid,
2303 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2304
2305 // This is so super not safe, that only the system (or okay root)
2306 // can do it.
2307 final int callingUid = Binder.getCallingUid();
2308 if (callingUid != 0 && callingUid != Process.myUid()) {
2309 throw new SecurityException(
2310 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 }
2312
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002313 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314 }
2315
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002316 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 // Remove any existing entries that are the same kind of task.
2318 int N = mRecentTasks.size();
2319 for (int i=0; i<N; i++) {
2320 TaskRecord tr = mRecentTasks.get(i);
2321 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2322 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2323 mRecentTasks.remove(i);
2324 i--;
2325 N--;
2326 if (task.intent == null) {
2327 // If the new recent task we are adding is not fully
2328 // specified, then replace it with the existing recent task.
2329 task = tr;
2330 }
2331 }
2332 }
2333 if (N >= MAX_RECENT_TASKS) {
2334 mRecentTasks.remove(N-1);
2335 }
2336 mRecentTasks.add(0, task);
2337 }
2338
2339 public void setRequestedOrientation(IBinder token,
2340 int requestedOrientation) {
2341 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002342 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002343 if (index < 0) {
2344 return;
2345 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002346 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002347 final long origId = Binder.clearCallingIdentity();
2348 mWindowManager.setAppOrientation(r, requestedOrientation);
2349 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002350 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 r.mayFreezeScreenLocked(r.app) ? r : null);
2352 if (config != null) {
2353 r.frozenBeforeDestroy = true;
2354 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002355 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002356 }
2357 }
2358 Binder.restoreCallingIdentity(origId);
2359 }
2360 }
2361
2362 public int getRequestedOrientation(IBinder token) {
2363 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002364 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002365 if (index < 0) {
2366 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2367 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002368 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 return mWindowManager.getAppOrientation(r);
2370 }
2371 }
2372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 /**
2374 * This is the internal entry point for handling Activity.finish().
2375 *
2376 * @param token The Binder token referencing the Activity we want to finish.
2377 * @param resultCode Result code, if any, from this Activity.
2378 * @param resultData Result data (Intent), if any, from this Activity.
2379 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002380 * @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 -08002381 */
2382 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2383 // Refuse possible leaked file descriptors
2384 if (resultData != null && resultData.hasFileDescriptors() == true) {
2385 throw new IllegalArgumentException("File descriptors passed in Intent");
2386 }
2387
2388 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002389 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002391 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002392 if (next != null) {
2393 // ask watcher if this is allowed
2394 boolean resumeOK = true;
2395 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002396 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002398 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002399 }
2400
2401 if (!resumeOK) {
2402 return false;
2403 }
2404 }
2405 }
2406 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002407 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002408 resultData, "app-request");
2409 Binder.restoreCallingIdentity(origId);
2410 return res;
2411 }
2412 }
2413
Dianne Hackborn860755f2010-06-03 18:47:52 -07002414 public final void finishHeavyWeightApp() {
2415 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2416 != PackageManager.PERMISSION_GRANTED) {
2417 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2418 + Binder.getCallingPid()
2419 + ", uid=" + Binder.getCallingUid()
2420 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2421 Slog.w(TAG, msg);
2422 throw new SecurityException(msg);
2423 }
2424
2425 synchronized(this) {
2426 if (mHeavyWeightProcess == null) {
2427 return;
2428 }
2429
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002430 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002431 mHeavyWeightProcess.activities);
2432 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002433 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002434 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002435 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002436 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002437 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002438 null, "finish-heavy");
2439 }
2440 }
2441 }
2442
2443 mHeavyWeightProcess = null;
2444 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2445 }
2446 }
2447
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002448 public void crashApplication(int uid, int initialPid, String packageName,
2449 String message) {
2450 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2451 != PackageManager.PERMISSION_GRANTED) {
2452 String msg = "Permission Denial: crashApplication() from pid="
2453 + Binder.getCallingPid()
2454 + ", uid=" + Binder.getCallingUid()
2455 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2456 Slog.w(TAG, msg);
2457 throw new SecurityException(msg);
2458 }
2459
2460 synchronized(this) {
2461 ProcessRecord proc = null;
2462
2463 // Figure out which process to kill. We don't trust that initialPid
2464 // still has any relation to current pids, so must scan through the
2465 // list.
2466 synchronized (mPidsSelfLocked) {
2467 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2468 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2469 if (p.info.uid != uid) {
2470 continue;
2471 }
2472 if (p.pid == initialPid) {
2473 proc = p;
2474 break;
2475 }
2476 for (String str : p.pkgList) {
2477 if (str.equals(packageName)) {
2478 proc = p;
2479 }
2480 }
2481 }
2482 }
2483
2484 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002485 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002486 + " initialPid=" + initialPid
2487 + " packageName=" + packageName);
2488 return;
2489 }
2490
2491 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002492 if (proc.pid == Process.myPid()) {
2493 Log.w(TAG, "crashApplication: trying to crash self!");
2494 return;
2495 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002496 long ident = Binder.clearCallingIdentity();
2497 try {
2498 proc.thread.scheduleCrash(message);
2499 } catch (RemoteException e) {
2500 }
2501 Binder.restoreCallingIdentity(ident);
2502 }
2503 }
2504 }
2505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 public final void finishSubActivity(IBinder token, String resultWho,
2507 int requestCode) {
2508 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002509 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 if (index < 0) {
2511 return;
2512 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002513 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002514
2515 final long origId = Binder.clearCallingIdentity();
2516
2517 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002518 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2519 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002520 if (r.resultTo == self && r.requestCode == requestCode) {
2521 if ((r.resultWho == null && resultWho == null) ||
2522 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002523 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 Activity.RESULT_CANCELED, null, "request-sub");
2525 }
2526 }
2527 }
2528
2529 Binder.restoreCallingIdentity(origId);
2530 }
2531 }
2532
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002533 public boolean willActivityBeVisible(IBinder token) {
2534 synchronized(this) {
2535 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002536 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2537 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002538 if (r == token) {
2539 return true;
2540 }
2541 if (r.fullscreen && !r.finishing) {
2542 return false;
2543 }
2544 }
2545 return true;
2546 }
2547 }
2548
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002549 public void overridePendingTransition(IBinder token, String packageName,
2550 int enterAnim, int exitAnim) {
2551 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002552 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002553 if (index < 0) {
2554 return;
2555 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002556 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002557
2558 final long origId = Binder.clearCallingIdentity();
2559
2560 if (self.state == ActivityState.RESUMED
2561 || self.state == ActivityState.PAUSING) {
2562 mWindowManager.overridePendingAppTransition(packageName,
2563 enterAnim, exitAnim);
2564 }
2565
2566 Binder.restoreCallingIdentity(origId);
2567 }
2568 }
2569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 * Main function for removing an existing process from the activity manager
2572 * as a result of that process going away. Clears out all connections
2573 * to the process.
2574 */
2575 private final void handleAppDiedLocked(ProcessRecord app,
2576 boolean restarting) {
2577 cleanUpApplicationRecordLocked(app, restarting, -1);
2578 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002579 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 }
2581
2582 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002583 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2584 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2585 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002587 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2588 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002589 }
2590
2591 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002592 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593
2594 boolean atTop = true;
2595 boolean hasVisibleActivities = false;
2596
2597 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002598 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002599 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 TAG, "Removing app " + app + " from history with " + i + " entries");
2601 while (i > 0) {
2602 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002603 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002604 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2606 if (r.app == app) {
2607 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002608 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609 TAG, "Removing this entry! frozen=" + r.haveState
2610 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002611 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002612
2613 r.inHistory = false;
2614 mWindowManager.removeAppToken(r);
2615 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002616 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002618 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619
2620 } else {
2621 // We have the current state for this activity, so
2622 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002623 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 TAG, "Keeping entry, setting app to null");
2625 if (r.visible) {
2626 hasVisibleActivities = true;
2627 }
2628 r.app = null;
2629 r.nowVisible = false;
2630 if (!r.haveState) {
2631 r.icicle = null;
2632 }
2633 }
2634
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002635 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002636 r.state = ActivityState.STOPPED;
2637 }
2638 atTop = false;
2639 }
2640
2641 app.activities.clear();
2642
2643 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002644 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002645 + " running instrumentation " + app.instrumentationClass);
2646 Bundle info = new Bundle();
2647 info.putString("shortMsg", "Process crashed.");
2648 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2649 }
2650
2651 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002652 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002653 // If there was nothing to resume, and we are not already
2654 // restarting this process, but there is a visible activity that
2655 // is hosted by the process... then make sure all visible
2656 // activities are running, taking care of restarting this
2657 // process.
2658 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002659 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002660 }
2661 }
2662 }
2663 }
2664
2665 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2666 IBinder threadBinder = thread.asBinder();
2667
2668 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002669 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2670 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2672 return i;
2673 }
2674 }
2675 return -1;
2676 }
2677
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002678 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 IApplicationThread thread) {
2680 if (thread == null) {
2681 return null;
2682 }
2683
2684 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002685 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002686 }
2687
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002688 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 IApplicationThread thread) {
2690
2691 mProcDeaths[0]++;
2692
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002693 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2694 synchronized (stats) {
2695 stats.noteProcessDiedLocked(app.info.uid, pid);
2696 }
2697
Magnus Edlund7bb25812010-02-24 15:45:06 +01002698 // Clean up already done if the process has been re-started.
2699 if (app.pid == pid && app.thread != null &&
2700 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002701 if (!app.killedBackground) {
2702 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2703 + ") has died.");
2704 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002705 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002706 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002707 TAG, "Dying app: " + app + ", pid: " + pid
2708 + ", thread: " + thread.asBinder());
2709 boolean doLowMem = app.instrumentationClass == null;
2710 handleAppDiedLocked(app, false);
2711
2712 if (doLowMem) {
2713 // If there are no longer any background processes running,
2714 // and the app that died was not running instrumentation,
2715 // then tell everyone we are now low on memory.
2716 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002717 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2718 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2720 haveBg = true;
2721 break;
2722 }
2723 }
2724
2725 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002726 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002727 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002728 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002729 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2730 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002731 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002732 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2733 // The low memory report is overriding any current
2734 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002735 // heavy/important/visible/foreground processes first.
2736 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002737 rec.lastRequestedGc = 0;
2738 } else {
2739 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002740 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002741 rec.reportLowMemory = true;
2742 rec.lastLowMemory = now;
2743 mProcessesToGc.remove(rec);
2744 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 }
2746 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002747 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 }
2749 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002750 } else if (app.pid != pid) {
2751 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002752 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002753 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002754 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002755 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002756 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002757 + thread.asBinder());
2758 }
2759 }
2760
Dan Egnor42471dd2010-01-07 17:25:22 -08002761 /**
2762 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002763 * @param clearTraces causes the dump file to be erased prior to the new
2764 * traces being written, if true; when false, the new traces will be
2765 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002766 * @param firstPids of dalvik VM processes to dump stack traces for first
2767 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002768 * @return file containing stack traces, or null if no dump file is configured
2769 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002770 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2771 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002772 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2773 if (tracesPath == null || tracesPath.length() == 0) {
2774 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002775 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002776
2777 File tracesFile = new File(tracesPath);
2778 try {
2779 File tracesDir = tracesFile.getParentFile();
2780 if (!tracesDir.exists()) tracesFile.mkdirs();
2781 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2782
Christopher Tate6ee412d2010-05-28 12:01:56 -07002783 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002784 tracesFile.createNewFile();
2785 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2786 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002787 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002788 return null;
2789 }
2790
2791 // Use a FileObserver to detect when traces finish writing.
2792 // The order of traces is considered important to maintain for legibility.
2793 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2794 public synchronized void onEvent(int event, String path) { notify(); }
2795 };
2796
2797 try {
2798 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002799
2800 // First collect all of the stacks of the most important pids.
2801 try {
2802 int num = firstPids.size();
2803 for (int i = 0; i < num; i++) {
2804 synchronized (observer) {
2805 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2806 observer.wait(200); // Wait for write-close, give up after 200msec
2807 }
2808 }
2809 } catch (InterruptedException e) {
2810 Log.wtf(TAG, e);
2811 }
2812
2813 // Next measure CPU usage.
2814 if (processStats != null) {
2815 processStats.init();
2816 System.gc();
2817 processStats.update();
2818 try {
2819 synchronized (processStats) {
2820 processStats.wait(500); // measure over 1/2 second.
2821 }
2822 } catch (InterruptedException e) {
2823 }
2824 processStats.update();
2825
2826 // We'll take the stack crawls of just the top apps using CPU.
2827 final int N = processStats.countWorkingStats();
2828 int numProcs = 0;
2829 for (int i=0; i<N && numProcs<5; i++) {
2830 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2831 if (lastPids.indexOfKey(stats.pid) >= 0) {
2832 numProcs++;
2833 try {
2834 synchronized (observer) {
2835 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2836 observer.wait(200); // Wait for write-close, give up after 200msec
2837 }
2838 } catch (InterruptedException e) {
2839 Log.wtf(TAG, e);
2840 }
2841
2842 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002843 }
2844 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002845
2846 return tracesFile;
2847
Dan Egnor42471dd2010-01-07 17:25:22 -08002848 } finally {
2849 observer.stopWatching();
2850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 }
2852
Jeff Brown4d94a762010-09-23 11:33:28 -07002853 private final class AppNotResponding implements Runnable {
2854 private final ProcessRecord mApp;
2855 private final String mAnnotation;
2856
2857 public AppNotResponding(ProcessRecord app, String annotation) {
2858 mApp = app;
2859 mAnnotation = annotation;
2860 }
2861
2862 @Override
2863 public void run() {
2864 appNotResponding(mApp, null, null, mAnnotation);
2865 }
2866 }
2867
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002868 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2869 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002870 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2871 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2872
Dianne Hackborn287952c2010-09-22 22:34:31 -07002873 if (mController != null) {
2874 try {
2875 // 0 == continue, -1 = kill process immediately
2876 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2877 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2878 } catch (RemoteException e) {
2879 mController = null;
2880 }
2881 }
2882
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002883 long anrTime = SystemClock.uptimeMillis();
2884 if (MONITOR_CPU_USAGE) {
2885 updateCpuStatsNow();
2886 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002887
2888 synchronized (this) {
2889 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2890 if (mShuttingDown) {
2891 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2892 return;
2893 } else if (app.notResponding) {
2894 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2895 return;
2896 } else if (app.crashing) {
2897 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2898 return;
2899 }
2900
2901 // In case we come through here for the same app before completing
2902 // this one, mark as anring now so we will bail out.
2903 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002904
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002905 // Log the ANR to the event log.
2906 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2907 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002908
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002909 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002910 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002911
2912 int parentPid = app.pid;
2913 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002914 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002915
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002916 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002917
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002918 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2919 ProcessRecord r = mLruProcesses.get(i);
2920 if (r != null && r.thread != null) {
2921 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002922 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2923 if (r.persistent) {
2924 firstPids.add(pid);
2925 } else {
2926 lastPids.put(pid, Boolean.TRUE);
2927 }
2928 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930 }
2931 }
2932
Dan Egnor42471dd2010-01-07 17:25:22 -08002933 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002934 StringBuilder info = mStringBuilder;
2935 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002936 info.append("ANR in ").append(app.processName);
2937 if (activity != null && activity.shortComponentName != null) {
2938 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002939 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002940 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002942 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002943 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002944 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002945 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947
Dianne Hackborn287952c2010-09-22 22:34:31 -07002948 final ProcessStats processStats = new ProcessStats(true);
2949
2950 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2951
Dan Egnor42471dd2010-01-07 17:25:22 -08002952 String cpuInfo = null;
2953 if (MONITOR_CPU_USAGE) {
2954 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002955 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002956 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002957 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002958 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002959 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 }
2961
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002962 info.append(processStats.printCurrentState(anrTime));
2963
Joe Onorato8a9b2202010-02-26 18:56:32 -08002964 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002965 if (tracesFile == null) {
2966 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2967 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2968 }
2969
2970 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2971
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002972 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002973 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002974 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2975 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002976 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002977 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2978 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002979 }
2980 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002981 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002982 }
2983 }
2984
Dan Egnor42471dd2010-01-07 17:25:22 -08002985 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2986 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2987 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002988
2989 synchronized (this) {
2990 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2991 Process.killProcess(app.pid);
2992 return;
2993 }
2994
2995 // Set the app's notResponding state, and look up the errorReportReceiver
2996 makeAppNotRespondingLocked(app,
2997 activity != null ? activity.shortComponentName : null,
2998 annotation != null ? "ANR " + annotation : "ANR",
2999 info.toString());
3000
3001 // Bring up the infamous App Not Responding dialog
3002 Message msg = Message.obtain();
3003 HashMap map = new HashMap();
3004 msg.what = SHOW_NOT_RESPONDING_MSG;
3005 msg.obj = map;
3006 map.put("app", app);
3007 if (activity != null) {
3008 map.put("activity", activity);
3009 }
3010
3011 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003012 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003013 }
3014
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003015 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3016 if (!mLaunchWarningShown) {
3017 mLaunchWarningShown = true;
3018 mHandler.post(new Runnable() {
3019 @Override
3020 public void run() {
3021 synchronized (ActivityManagerService.this) {
3022 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3023 d.show();
3024 mHandler.postDelayed(new Runnable() {
3025 @Override
3026 public void run() {
3027 synchronized (ActivityManagerService.this) {
3028 d.dismiss();
3029 mLaunchWarningShown = false;
3030 }
3031 }
3032 }, 4000);
3033 }
3034 }
3035 });
3036 }
3037 }
3038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003039 public boolean clearApplicationUserData(final String packageName,
3040 final IPackageDataObserver observer) {
3041 int uid = Binder.getCallingUid();
3042 int pid = Binder.getCallingPid();
3043 long callingId = Binder.clearCallingIdentity();
3044 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003045 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 int pkgUid = -1;
3047 synchronized(this) {
3048 try {
3049 pkgUid = pm.getPackageUid(packageName);
3050 } catch (RemoteException e) {
3051 }
3052 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003053 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 return false;
3055 }
3056 if (uid == pkgUid || checkComponentPermission(
3057 android.Manifest.permission.CLEAR_APP_USER_DATA,
3058 pid, uid, -1)
3059 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003060 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003061 } else {
3062 throw new SecurityException(pid+" does not have permission:"+
3063 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3064 "for process:"+packageName);
3065 }
3066 }
3067
3068 try {
3069 //clear application user data
3070 pm.clearApplicationUserData(packageName, observer);
3071 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3072 Uri.fromParts("package", packageName, null));
3073 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003074 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3075 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003076 } catch (RemoteException e) {
3077 }
3078 } finally {
3079 Binder.restoreCallingIdentity(callingId);
3080 }
3081 return true;
3082 }
3083
Dianne Hackborn03abb812010-01-04 18:43:19 -08003084 public void killBackgroundProcesses(final String packageName) {
3085 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3086 != PackageManager.PERMISSION_GRANTED &&
3087 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3088 != PackageManager.PERMISSION_GRANTED) {
3089 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 + Binder.getCallingPid()
3091 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003092 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003093 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094 throw new SecurityException(msg);
3095 }
3096
3097 long callingId = Binder.clearCallingIdentity();
3098 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003099 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 int pkgUid = -1;
3101 synchronized(this) {
3102 try {
3103 pkgUid = pm.getPackageUid(packageName);
3104 } catch (RemoteException e) {
3105 }
3106 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003107 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108 return;
3109 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003110 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003111 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003112 }
3113 } finally {
3114 Binder.restoreCallingIdentity(callingId);
3115 }
3116 }
3117
3118 public void forceStopPackage(final String packageName) {
3119 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3120 != PackageManager.PERMISSION_GRANTED) {
3121 String msg = "Permission Denial: forceStopPackage() from pid="
3122 + Binder.getCallingPid()
3123 + ", uid=" + Binder.getCallingUid()
3124 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003125 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003126 throw new SecurityException(msg);
3127 }
3128
3129 long callingId = Binder.clearCallingIdentity();
3130 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003131 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003132 int pkgUid = -1;
3133 synchronized(this) {
3134 try {
3135 pkgUid = pm.getPackageUid(packageName);
3136 } catch (RemoteException e) {
3137 }
3138 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003139 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003140 return;
3141 }
3142 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 }
3144 } finally {
3145 Binder.restoreCallingIdentity(callingId);
3146 }
3147 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003148
3149 /*
3150 * The pkg name and uid have to be specified.
3151 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3152 */
3153 public void killApplicationWithUid(String pkg, int uid) {
3154 if (pkg == null) {
3155 return;
3156 }
3157 // Make sure the uid is valid.
3158 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003159 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003160 return;
3161 }
3162 int callerUid = Binder.getCallingUid();
3163 // Only the system server can kill an application
3164 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003165 // Post an aysnc message to kill the application
3166 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3167 msg.arg1 = uid;
3168 msg.arg2 = 0;
3169 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003170 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003171 } else {
3172 throw new SecurityException(callerUid + " cannot kill pkg: " +
3173 pkg);
3174 }
3175 }
3176
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003177 public void closeSystemDialogs(String reason) {
3178 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003179 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003180 if (reason != null) {
3181 intent.putExtra("reason", reason);
3182 }
3183
3184 final int uid = Binder.getCallingUid();
3185 final long origId = Binder.clearCallingIdentity();
3186 synchronized (this) {
3187 int i = mWatchers.beginBroadcast();
3188 while (i > 0) {
3189 i--;
3190 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3191 if (w != null) {
3192 try {
3193 w.closingSystemDialogs(reason);
3194 } catch (RemoteException e) {
3195 }
3196 }
3197 }
3198 mWatchers.finishBroadcast();
3199
Dianne Hackbornffa42482009-09-23 22:20:11 -07003200 mWindowManager.closeSystemDialogs(reason);
3201
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003202 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3203 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003204 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003205 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003206 Activity.RESULT_CANCELED, null, "close-sys");
3207 }
3208 }
3209
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003210 broadcastIntentLocked(null, null, intent, null,
3211 null, 0, null, null, null, false, false, -1, uid);
3212 }
3213 Binder.restoreCallingIdentity(origId);
3214 }
3215
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003216 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003217 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003218 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3219 for (int i=pids.length-1; i>=0; i--) {
3220 infos[i] = new Debug.MemoryInfo();
3221 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003222 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003223 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003224 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003225
3226 public void killApplicationProcess(String processName, int uid) {
3227 if (processName == null) {
3228 return;
3229 }
3230
3231 int callerUid = Binder.getCallingUid();
3232 // Only the system server can kill an application
3233 if (callerUid == Process.SYSTEM_UID) {
3234 synchronized (this) {
3235 ProcessRecord app = getProcessRecordLocked(processName, uid);
3236 if (app != null) {
3237 try {
3238 app.thread.scheduleSuicide();
3239 } catch (RemoteException e) {
3240 // If the other end already died, then our work here is done.
3241 }
3242 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003243 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003244 + processName + " / " + uid);
3245 }
3246 }
3247 } else {
3248 throw new SecurityException(callerUid + " cannot kill app process: " +
3249 processName);
3250 }
3251 }
3252
Dianne Hackborn03abb812010-01-04 18:43:19 -08003253 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003254 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3256 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003257 if (!mProcessesReady) {
3258 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003260 intent.putExtra(Intent.EXTRA_UID, uid);
3261 broadcastIntentLocked(null, null, intent,
3262 null, null, 0, null, null, null,
3263 false, false, MY_PID, Process.SYSTEM_UID);
3264 }
3265
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003266 private final boolean killPackageProcessesLocked(String packageName, int uid,
3267 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003268 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269
Dianne Hackborn03abb812010-01-04 18:43:19 -08003270 // Remove all processes this package may have touched: all with the
3271 // same UID (except for the system or root user), and all whose name
3272 // matches the package name.
3273 final String procNamePrefix = packageName + ":";
3274 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3275 final int NA = apps.size();
3276 for (int ia=0; ia<NA; ia++) {
3277 ProcessRecord app = apps.valueAt(ia);
3278 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003279 if (doit) {
3280 procs.add(app);
3281 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003282 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3283 || app.processName.equals(packageName)
3284 || app.processName.startsWith(procNamePrefix)) {
3285 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003286 if (!doit) {
3287 return true;
3288 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003289 app.removed = true;
3290 procs.add(app);
3291 }
3292 }
3293 }
3294 }
3295
3296 int N = procs.size();
3297 for (int i=0; i<N; i++) {
3298 removeProcessLocked(procs.get(i), callerWillRestart);
3299 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003300 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003301 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003302
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003303 private final boolean forceStopPackageLocked(String name, int uid,
3304 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 int i, N;
3306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003307 if (uid < 0) {
3308 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003309 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 } catch (RemoteException e) {
3311 }
3312 }
3313
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003314 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003315 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003316
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003317 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3318 while (badApps.hasNext()) {
3319 SparseArray<Long> ba = badApps.next();
3320 if (ba.get(uid) != null) {
3321 badApps.remove();
3322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 }
3324 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003325
3326 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3327 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003329 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3330 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003331 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003332 if (!doit) {
3333 return true;
3334 }
3335 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003336 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337 if (r.app != null) {
3338 r.app.removed = true;
3339 }
3340 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003341 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 }
3343 }
3344
3345 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3346 for (ServiceRecord service : mServices.values()) {
3347 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003348 if (!doit) {
3349 return true;
3350 }
3351 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003352 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 if (service.app != null) {
3354 service.app.removed = true;
3355 }
3356 service.app = null;
3357 services.add(service);
3358 }
3359 }
3360
3361 N = services.size();
3362 for (i=0; i<N; i++) {
3363 bringDownServiceLocked(services.get(i), true);
3364 }
3365
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003366 if (doit) {
3367 if (purgeCache) {
3368 AttributeCache ac = AttributeCache.instance();
3369 if (ac != null) {
3370 ac.removePackage(name);
3371 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003372 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003373 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003374 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003375
3376 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 }
3378
3379 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3380 final String name = app.processName;
3381 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003382 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383 TAG, "Force removing process " + app + " (" + name
3384 + "/" + uid + ")");
3385
3386 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003387 if (mHeavyWeightProcess == app) {
3388 mHeavyWeightProcess = null;
3389 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3390 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391 boolean needRestart = false;
3392 if (app.pid > 0 && app.pid != MY_PID) {
3393 int pid = app.pid;
3394 synchronized (mPidsSelfLocked) {
3395 mPidsSelfLocked.remove(pid);
3396 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3397 }
3398 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003399 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 Process.killProcess(pid);
3401
3402 if (app.persistent) {
3403 if (!callerWillRestart) {
3404 addAppLocked(app.info);
3405 } else {
3406 needRestart = true;
3407 }
3408 }
3409 } else {
3410 mRemovedProcesses.add(app);
3411 }
3412
3413 return needRestart;
3414 }
3415
3416 private final void processStartTimedOutLocked(ProcessRecord app) {
3417 final int pid = app.pid;
3418 boolean gone = false;
3419 synchronized (mPidsSelfLocked) {
3420 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3421 if (knownApp != null && knownApp.thread == null) {
3422 mPidsSelfLocked.remove(pid);
3423 gone = true;
3424 }
3425 }
3426
3427 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003428 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003429 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003430 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003431 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003432 if (mHeavyWeightProcess == app) {
3433 mHeavyWeightProcess = null;
3434 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3435 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003436 // Take care of any launching providers waiting for this process.
3437 checkAppInLaunchingProvidersLocked(app, true);
3438 // Take care of any services that are waiting for the process.
3439 for (int i=0; i<mPendingServices.size(); i++) {
3440 ServiceRecord sr = mPendingServices.get(i);
3441 if (app.info.uid == sr.appInfo.uid
3442 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003443 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003444 mPendingServices.remove(i);
3445 i--;
3446 bringDownServiceLocked(sr, true);
3447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003449 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003450 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003451 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003452 try {
3453 IBackupManager bm = IBackupManager.Stub.asInterface(
3454 ServiceManager.getService(Context.BACKUP_SERVICE));
3455 bm.agentDisconnected(app.info.packageName);
3456 } catch (RemoteException e) {
3457 // Can't happen; the backup manager is local
3458 }
3459 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003460 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003461 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003462 mPendingBroadcast.state = BroadcastRecord.IDLE;
3463 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003464 mPendingBroadcast = null;
3465 scheduleBroadcastsLocked();
3466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003467 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003468 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469 }
3470 }
3471
3472 private final boolean attachApplicationLocked(IApplicationThread thread,
3473 int pid) {
3474
3475 // Find the application record that is being attached... either via
3476 // the pid if we are running in multiple processes, or just pull the
3477 // next app record if we are emulating process with anonymous threads.
3478 ProcessRecord app;
3479 if (pid != MY_PID && pid >= 0) {
3480 synchronized (mPidsSelfLocked) {
3481 app = mPidsSelfLocked.get(pid);
3482 }
3483 } else if (mStartingProcesses.size() > 0) {
3484 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003485 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003486 } else {
3487 app = null;
3488 }
3489
3490 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003491 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003493 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494 if (pid > 0 && pid != MY_PID) {
3495 Process.killProcess(pid);
3496 } else {
3497 try {
3498 thread.scheduleExit();
3499 } catch (Exception e) {
3500 // Ignore exceptions.
3501 }
3502 }
3503 return false;
3504 }
3505
3506 // If this application record is still attached to a previous
3507 // process, clean it up now.
3508 if (app.thread != null) {
3509 handleAppDiedLocked(app, true);
3510 }
3511
3512 // Tell the process all about itself.
3513
Joe Onorato8a9b2202010-02-26 18:56:32 -08003514 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 TAG, "Binding process pid " + pid + " to record " + app);
3516
3517 String processName = app.processName;
3518 try {
3519 thread.asBinder().linkToDeath(new AppDeathRecipient(
3520 app, pid, thread), 0);
3521 } catch (RemoteException e) {
3522 app.resetPackageList();
3523 startProcessLocked(app, "link fail", processName);
3524 return false;
3525 }
3526
Doug Zongker2bec3d42009-12-04 12:52:44 -08003527 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528
3529 app.thread = thread;
3530 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003531 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3532 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 app.forcingToForeground = null;
3534 app.foregroundServices = false;
3535 app.debugging = false;
3536
3537 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3538
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003539 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003540 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003541
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003542 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003543 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003544 }
3545
Joe Onorato8a9b2202010-02-26 18:56:32 -08003546 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003547 TAG, "New app record " + app
3548 + " thread=" + thread.asBinder() + " pid=" + pid);
3549 try {
3550 int testMode = IApplicationThread.DEBUG_OFF;
3551 if (mDebugApp != null && mDebugApp.equals(processName)) {
3552 testMode = mWaitForDebugger
3553 ? IApplicationThread.DEBUG_WAIT
3554 : IApplicationThread.DEBUG_ON;
3555 app.debugging = true;
3556 if (mDebugTransient) {
3557 mDebugApp = mOrigDebugApp;
3558 mWaitForDebugger = mOrigWaitForDebugger;
3559 }
3560 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003561
Christopher Tate181fafa2009-05-14 11:12:14 -07003562 // If the app is being launched for restore or full backup, set it up specially
3563 boolean isRestrictedBackupMode = false;
3564 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3565 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3566 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3567 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003568
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003569 ensurePackageDexOpt(app.instrumentationInfo != null
3570 ? app.instrumentationInfo.packageName
3571 : app.info.packageName);
3572 if (app.instrumentationClass != null) {
3573 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003574 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003575 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003576 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003577 thread.bindApplication(processName, app.instrumentationInfo != null
3578 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003579 app.instrumentationClass, app.instrumentationProfileFile,
3580 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003581 isRestrictedBackupMode || !normalMode,
3582 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003583 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003584 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003585 } catch (Exception e) {
3586 // todo: Yikes! What should we do? For now we will try to
3587 // start another process, but that could easily get us in
3588 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003589 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590
3591 app.resetPackageList();
3592 startProcessLocked(app, "bind fail", processName);
3593 return false;
3594 }
3595
3596 // Remove this record from the list of starting applications.
3597 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003598 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3599 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600 mProcessesOnHold.remove(app);
3601
3602 boolean badApp = false;
3603 boolean didSomething = false;
3604
3605 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003606 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003607 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3609 && processName.equals(hr.processName)) {
3610 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003611 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003612 didSomething = true;
3613 }
3614 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003615 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 + hr.intent.getComponent().flattenToShortString(), e);
3617 badApp = true;
3618 }
3619 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003620 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 }
3622 }
3623
3624 // Find any services that should be running in this process...
3625 if (!badApp && mPendingServices.size() > 0) {
3626 ServiceRecord sr = null;
3627 try {
3628 for (int i=0; i<mPendingServices.size(); i++) {
3629 sr = mPendingServices.get(i);
3630 if (app.info.uid != sr.appInfo.uid
3631 || !processName.equals(sr.processName)) {
3632 continue;
3633 }
3634
3635 mPendingServices.remove(i);
3636 i--;
3637 realStartServiceLocked(sr, app);
3638 didSomething = true;
3639 }
3640 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003641 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 + sr.shortName, e);
3643 badApp = true;
3644 }
3645 }
3646
3647 // Check if the next broadcast receiver is in this process...
3648 BroadcastRecord br = mPendingBroadcast;
3649 if (!badApp && br != null && br.curApp == app) {
3650 try {
3651 mPendingBroadcast = null;
3652 processCurBroadcastLocked(br, app);
3653 didSomething = true;
3654 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003655 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003656 + br.curComponent.flattenToShortString(), e);
3657 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003658 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3660 br.resultExtras, br.resultAbort, true);
3661 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003662 // We need to reset the state if we fails to start the receiver.
3663 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 }
3665 }
3666
Christopher Tate181fafa2009-05-14 11:12:14 -07003667 // Check whether the next backup agent is in this process...
3668 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003669 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003670 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003671 try {
3672 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3673 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003674 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003675 e.printStackTrace();
3676 }
3677 }
3678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003679 if (badApp) {
3680 // todo: Also need to kill application to deal with all
3681 // kinds of exceptions.
3682 handleAppDiedLocked(app, false);
3683 return false;
3684 }
3685
3686 if (!didSomething) {
3687 updateOomAdjLocked();
3688 }
3689
3690 return true;
3691 }
3692
3693 public final void attachApplication(IApplicationThread thread) {
3694 synchronized (this) {
3695 int callingPid = Binder.getCallingPid();
3696 final long origId = Binder.clearCallingIdentity();
3697 attachApplicationLocked(thread, callingPid);
3698 Binder.restoreCallingIdentity(origId);
3699 }
3700 }
3701
Dianne Hackborne88846e2009-09-30 21:34:25 -07003702 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003703 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003704 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003705 Binder.restoreCallingIdentity(origId);
3706 }
3707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003709 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003710 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003711 mWindowManager.enableScreenAfterBoot();
3712 }
3713
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003714 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003715 IntentFilter pkgFilter = new IntentFilter();
3716 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3717 pkgFilter.addDataScheme("package");
3718 mContext.registerReceiver(new BroadcastReceiver() {
3719 @Override
3720 public void onReceive(Context context, Intent intent) {
3721 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3722 if (pkgs != null) {
3723 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003724 synchronized (ActivityManagerService.this) {
3725 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3726 setResultCode(Activity.RESULT_OK);
3727 return;
3728 }
3729 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003730 }
3731 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003732 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003733 }, pkgFilter);
3734
3735 synchronized (this) {
3736 // Ensure that any processes we had put on hold are now started
3737 // up.
3738 final int NP = mProcessesOnHold.size();
3739 if (NP > 0) {
3740 ArrayList<ProcessRecord> procs =
3741 new ArrayList<ProcessRecord>(mProcessesOnHold);
3742 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003743 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3744 + procs.get(ip));
3745 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003746 }
3747 }
3748
3749 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003750 // Start looking for apps that are abusing wake locks.
3751 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003752 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003753 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003754 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003755 broadcastIntentLocked(null, null,
3756 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3757 null, null, 0, null, null,
3758 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3759 false, false, MY_PID, Process.SYSTEM_UID);
3760 }
3761 }
3762 }
3763
3764 final void ensureBootCompleted() {
3765 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003766 boolean enableScreen;
3767 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003768 booting = mBooting;
3769 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003770 enableScreen = !mBooted;
3771 mBooted = true;
3772 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003773
3774 if (booting) {
3775 finishBooting();
3776 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003777
3778 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003779 enableScreenAfterBoot();
3780 }
3781 }
3782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 public final void activityPaused(IBinder token, Bundle icicle) {
3784 // Refuse possible leaked file descriptors
3785 if (icicle != null && icicle.hasFileDescriptors()) {
3786 throw new IllegalArgumentException("File descriptors passed in Bundle");
3787 }
3788
3789 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003790 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003791 Binder.restoreCallingIdentity(origId);
3792 }
3793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 public final void activityStopped(IBinder token, Bitmap thumbnail,
3795 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003796 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003797 TAG, "Activity stopped: token=" + token);
3798
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003799 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800
3801 final long origId = Binder.clearCallingIdentity();
3802
3803 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003804 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003806 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 r.thumbnail = thumbnail;
3808 r.description = description;
3809 r.stopped = true;
3810 r.state = ActivityState.STOPPED;
3811 if (!r.finishing) {
3812 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003813 r.stack.destroyActivityLocked(r, true);
3814 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003815 }
3816 }
3817 }
3818 }
3819
3820 if (r != null) {
3821 sendPendingThumbnail(r, null, null, null, false);
3822 }
3823
3824 trimApplications();
3825
3826 Binder.restoreCallingIdentity(origId);
3827 }
3828
3829 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003830 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003831 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 }
3833
3834 public String getCallingPackage(IBinder token) {
3835 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003836 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003837 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 }
3839 }
3840
3841 public ComponentName getCallingActivity(IBinder token) {
3842 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003843 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003844 return r != null ? r.intent.getComponent() : null;
3845 }
3846 }
3847
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003848 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003849 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003850 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003851 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003852 if (r != null) {
3853 return r.resultTo;
3854 }
3855 }
3856 return null;
3857 }
3858
3859 public ComponentName getActivityClassForToken(IBinder token) {
3860 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003861 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003863 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 return r.intent.getComponent();
3865 }
3866 return null;
3867 }
3868 }
3869
3870 public String getPackageForToken(IBinder token) {
3871 synchronized(this) {
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 return r.packageName;
3876 }
3877 return null;
3878 }
3879 }
3880
3881 public IIntentSender getIntentSender(int type,
3882 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003883 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003884 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003885 if (intents != null) {
3886 if (intents.length < 1) {
3887 throw new IllegalArgumentException("Intents array length must be >= 1");
3888 }
3889 for (int i=0; i<intents.length; i++) {
3890 Intent intent = intents[i];
3891 if (intent == null) {
3892 throw new IllegalArgumentException("Null intent at index " + i);
3893 }
3894 if (intent.hasFileDescriptors()) {
3895 throw new IllegalArgumentException("File descriptors passed in Intent");
3896 }
3897 if (type == INTENT_SENDER_BROADCAST &&
3898 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3899 throw new IllegalArgumentException(
3900 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3901 }
3902 intents[i] = new Intent(intent);
3903 }
3904 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003905 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003906 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003907 }
3908 }
3909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 synchronized(this) {
3911 int callingUid = Binder.getCallingUid();
3912 try {
3913 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3914 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003915 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 .getPackageUid(packageName);
3917 if (uid != Binder.getCallingUid()) {
3918 String msg = "Permission Denial: getIntentSender() from pid="
3919 + Binder.getCallingPid()
3920 + ", uid=" + Binder.getCallingUid()
3921 + ", (need uid=" + uid + ")"
3922 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003923 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003924 throw new SecurityException(msg);
3925 }
3926 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003927
3928 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003929 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003931 } catch (RemoteException e) {
3932 throw new SecurityException(e);
3933 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003934 }
3935 }
3936
3937 IIntentSender getIntentSenderLocked(int type,
3938 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003939 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003940 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003941 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003942 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003943 if (index < 0) {
3944 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003946 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003947 if (activity.finishing) {
3948 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003949 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003950 }
3951
3952 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3953 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3954 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3955 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3956 |PendingIntent.FLAG_UPDATE_CURRENT);
3957
3958 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3959 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003960 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003961 WeakReference<PendingIntentRecord> ref;
3962 ref = mIntentSenderRecords.get(key);
3963 PendingIntentRecord rec = ref != null ? ref.get() : null;
3964 if (rec != null) {
3965 if (!cancelCurrent) {
3966 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003967 if (rec.key.requestIntent != null) {
3968 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3969 }
3970 if (intents != null) {
3971 intents[intents.length-1] = rec.key.requestIntent;
3972 rec.key.allIntents = intents;
3973 rec.key.allResolvedTypes = resolvedTypes;
3974 } else {
3975 rec.key.allIntents = null;
3976 rec.key.allResolvedTypes = null;
3977 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 return rec;
3980 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003981 rec.canceled = true;
3982 mIntentSenderRecords.remove(key);
3983 }
3984 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003985 return rec;
3986 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003987 rec = new PendingIntentRecord(this, key, callingUid);
3988 mIntentSenderRecords.put(key, rec.ref);
3989 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3990 if (activity.pendingResults == null) {
3991 activity.pendingResults
3992 = new HashSet<WeakReference<PendingIntentRecord>>();
3993 }
3994 activity.pendingResults.add(rec.ref);
3995 }
3996 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003997 }
3998
3999 public void cancelIntentSender(IIntentSender sender) {
4000 if (!(sender instanceof PendingIntentRecord)) {
4001 return;
4002 }
4003 synchronized(this) {
4004 PendingIntentRecord rec = (PendingIntentRecord)sender;
4005 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004006 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004007 .getPackageUid(rec.key.packageName);
4008 if (uid != Binder.getCallingUid()) {
4009 String msg = "Permission Denial: cancelIntentSender() from pid="
4010 + Binder.getCallingPid()
4011 + ", uid=" + Binder.getCallingUid()
4012 + " is not allowed to cancel packges "
4013 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004014 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 throw new SecurityException(msg);
4016 }
4017 } catch (RemoteException e) {
4018 throw new SecurityException(e);
4019 }
4020 cancelIntentSenderLocked(rec, true);
4021 }
4022 }
4023
4024 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4025 rec.canceled = true;
4026 mIntentSenderRecords.remove(rec.key);
4027 if (cleanActivity && rec.key.activity != null) {
4028 rec.key.activity.pendingResults.remove(rec.ref);
4029 }
4030 }
4031
4032 public String getPackageForIntentSender(IIntentSender pendingResult) {
4033 if (!(pendingResult instanceof PendingIntentRecord)) {
4034 return null;
4035 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004036 try {
4037 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4038 return res.key.packageName;
4039 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004040 }
4041 return null;
4042 }
4043
4044 public void setProcessLimit(int max) {
4045 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4046 "setProcessLimit()");
4047 mProcessLimit = max;
4048 }
4049
4050 public int getProcessLimit() {
4051 return mProcessLimit;
4052 }
4053
4054 void foregroundTokenDied(ForegroundToken token) {
4055 synchronized (ActivityManagerService.this) {
4056 synchronized (mPidsSelfLocked) {
4057 ForegroundToken cur
4058 = mForegroundProcesses.get(token.pid);
4059 if (cur != token) {
4060 return;
4061 }
4062 mForegroundProcesses.remove(token.pid);
4063 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4064 if (pr == null) {
4065 return;
4066 }
4067 pr.forcingToForeground = null;
4068 pr.foregroundServices = false;
4069 }
4070 updateOomAdjLocked();
4071 }
4072 }
4073
4074 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4075 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4076 "setProcessForeground()");
4077 synchronized(this) {
4078 boolean changed = false;
4079
4080 synchronized (mPidsSelfLocked) {
4081 ProcessRecord pr = mPidsSelfLocked.get(pid);
4082 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004083 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004084 return;
4085 }
4086 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4087 if (oldToken != null) {
4088 oldToken.token.unlinkToDeath(oldToken, 0);
4089 mForegroundProcesses.remove(pid);
4090 pr.forcingToForeground = null;
4091 changed = true;
4092 }
4093 if (isForeground && token != null) {
4094 ForegroundToken newToken = new ForegroundToken() {
4095 public void binderDied() {
4096 foregroundTokenDied(this);
4097 }
4098 };
4099 newToken.pid = pid;
4100 newToken.token = token;
4101 try {
4102 token.linkToDeath(newToken, 0);
4103 mForegroundProcesses.put(pid, newToken);
4104 pr.forcingToForeground = token;
4105 changed = true;
4106 } catch (RemoteException e) {
4107 // If the process died while doing this, we will later
4108 // do the cleanup with the process death link.
4109 }
4110 }
4111 }
4112
4113 if (changed) {
4114 updateOomAdjLocked();
4115 }
4116 }
4117 }
4118
4119 // =========================================================
4120 // PERMISSIONS
4121 // =========================================================
4122
4123 static class PermissionController extends IPermissionController.Stub {
4124 ActivityManagerService mActivityManagerService;
4125 PermissionController(ActivityManagerService activityManagerService) {
4126 mActivityManagerService = activityManagerService;
4127 }
4128
4129 public boolean checkPermission(String permission, int pid, int uid) {
4130 return mActivityManagerService.checkPermission(permission, pid,
4131 uid) == PackageManager.PERMISSION_GRANTED;
4132 }
4133 }
4134
4135 /**
4136 * This can be called with or without the global lock held.
4137 */
4138 int checkComponentPermission(String permission, int pid, int uid,
4139 int reqUid) {
4140 // We might be performing an operation on behalf of an indirect binder
4141 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4142 // client identity accordingly before proceeding.
4143 Identity tlsIdentity = sCallerIdentity.get();
4144 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004145 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004146 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4147 uid = tlsIdentity.uid;
4148 pid = tlsIdentity.pid;
4149 }
4150
4151 // Root, system server and our own process get to do everything.
4152 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4153 !Process.supportsProcesses()) {
4154 return PackageManager.PERMISSION_GRANTED;
4155 }
4156 // If the target requires a specific UID, always fail for others.
4157 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004158 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004159 return PackageManager.PERMISSION_DENIED;
4160 }
4161 if (permission == null) {
4162 return PackageManager.PERMISSION_GRANTED;
4163 }
4164 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004165 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 .checkUidPermission(permission, uid);
4167 } catch (RemoteException e) {
4168 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004169 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 }
4171 return PackageManager.PERMISSION_DENIED;
4172 }
4173
4174 /**
4175 * As the only public entry point for permissions checking, this method
4176 * can enforce the semantic that requesting a check on a null global
4177 * permission is automatically denied. (Internally a null permission
4178 * string is used when calling {@link #checkComponentPermission} in cases
4179 * when only uid-based security is needed.)
4180 *
4181 * This can be called with or without the global lock held.
4182 */
4183 public int checkPermission(String permission, int pid, int uid) {
4184 if (permission == null) {
4185 return PackageManager.PERMISSION_DENIED;
4186 }
4187 return checkComponentPermission(permission, pid, uid, -1);
4188 }
4189
4190 /**
4191 * Binder IPC calls go through the public entry point.
4192 * This can be called with or without the global lock held.
4193 */
4194 int checkCallingPermission(String permission) {
4195 return checkPermission(permission,
4196 Binder.getCallingPid(),
4197 Binder.getCallingUid());
4198 }
4199
4200 /**
4201 * This can be called with or without the global lock held.
4202 */
4203 void enforceCallingPermission(String permission, String func) {
4204 if (checkCallingPermission(permission)
4205 == PackageManager.PERMISSION_GRANTED) {
4206 return;
4207 }
4208
4209 String msg = "Permission Denial: " + func + " from pid="
4210 + Binder.getCallingPid()
4211 + ", uid=" + Binder.getCallingUid()
4212 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004213 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004214 throw new SecurityException(msg);
4215 }
4216
4217 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004218 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4219 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4220 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4221 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4222 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004224 // Is the component private from the target uid?
4225 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4226
4227 // Acceptable if the there is no read permission needed from the
4228 // target or the target is holding the read permission.
4229 if (!readPerm) {
4230 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004231 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004232 == PackageManager.PERMISSION_GRANTED)) {
4233 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 }
4235 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004236
4237 // Acceptable if the there is no write permission needed from the
4238 // target or the target is holding the read permission.
4239 if (!writePerm) {
4240 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004241 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004242 == PackageManager.PERMISSION_GRANTED)) {
4243 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004244 }
4245 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004246
4247 // Acceptable if there is a path permission matching the URI that
4248 // the target holds the permission on.
4249 PathPermission[] pps = pi.pathPermissions;
4250 if (pps != null && (!readPerm || !writePerm)) {
4251 final String path = uri.getPath();
4252 int i = pps.length;
4253 while (i > 0 && (!readPerm || !writePerm)) {
4254 i--;
4255 PathPermission pp = pps[i];
4256 if (!readPerm) {
4257 final String pprperm = pp.getReadPermission();
4258 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4259 + pprperm + " for " + pp.getPath()
4260 + ": match=" + pp.match(path)
4261 + " check=" + pm.checkUidPermission(pprperm, uid));
4262 if (pprperm != null && pp.match(path) &&
4263 (pm.checkUidPermission(pprperm, uid)
4264 == PackageManager.PERMISSION_GRANTED)) {
4265 readPerm = true;
4266 }
4267 }
4268 if (!writePerm) {
4269 final String ppwperm = pp.getWritePermission();
4270 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4271 + ppwperm + " for " + pp.getPath()
4272 + ": match=" + pp.match(path)
4273 + " check=" + pm.checkUidPermission(ppwperm, uid));
4274 if (ppwperm != null && pp.match(path) &&
4275 (pm.checkUidPermission(ppwperm, uid)
4276 == PackageManager.PERMISSION_GRANTED)) {
4277 writePerm = true;
4278 }
4279 }
4280 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 } catch (RemoteException e) {
4283 return false;
4284 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004285
4286 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287 }
4288
4289 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4290 int modeFlags) {
4291 // Root gets to do everything.
4292 if (uid == 0 || !Process.supportsProcesses()) {
4293 return true;
4294 }
4295 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4296 if (perms == null) return false;
4297 UriPermission perm = perms.get(uri);
4298 if (perm == null) return false;
4299 return (modeFlags&perm.modeFlags) == modeFlags;
4300 }
4301
4302 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4303 // Another redirected-binder-call permissions check as in
4304 // {@link checkComponentPermission}.
4305 Identity tlsIdentity = sCallerIdentity.get();
4306 if (tlsIdentity != null) {
4307 uid = tlsIdentity.uid;
4308 pid = tlsIdentity.pid;
4309 }
4310
4311 // Our own process gets to do everything.
4312 if (pid == MY_PID) {
4313 return PackageManager.PERMISSION_GRANTED;
4314 }
4315 synchronized(this) {
4316 return checkUriPermissionLocked(uri, uid, modeFlags)
4317 ? PackageManager.PERMISSION_GRANTED
4318 : PackageManager.PERMISSION_DENIED;
4319 }
4320 }
4321
Dianne Hackborn39792d22010-08-19 18:01:52 -07004322 /**
4323 * Check if the targetPkg can be granted permission to access uri by
4324 * the callingUid using the given modeFlags. Throws a security exception
4325 * if callingUid is not allowed to do this. Returns the uid of the target
4326 * if the URI permission grant should be performed; returns -1 if it is not
4327 * needed (for example targetPkg already has permission to access the URI).
4328 */
4329 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4330 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004331 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4332 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4333 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004334 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004335 }
4336
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004337 if (targetPkg != null) {
4338 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4339 "Checking grant " + targetPkg + " permission to " + uri);
4340 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004341
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004342 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004343
4344 // If this is not a content: uri, we can't do anything with it.
4345 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004346 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004347 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004348 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 }
4350
4351 String name = uri.getAuthority();
4352 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004353 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004354 if (cpr != null) {
4355 pi = cpr.info;
4356 } else {
4357 try {
4358 pi = pm.resolveContentProvider(name,
4359 PackageManager.GET_URI_PERMISSION_PATTERNS);
4360 } catch (RemoteException ex) {
4361 }
4362 }
4363 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004364 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004365 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 }
4367
4368 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004369 if (targetPkg != null) {
4370 try {
4371 targetUid = pm.getPackageUid(targetPkg);
4372 if (targetUid < 0) {
4373 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4374 "Can't grant URI permission no uid for: " + targetPkg);
4375 return -1;
4376 }
4377 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004378 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004379 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004380 } else {
4381 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004382 }
4383
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004384 if (targetUid >= 0) {
4385 // First... does the target actually need this permission?
4386 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4387 // No need to grant the target this permission.
4388 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4389 "Target " + targetPkg + " already has full permission to " + uri);
4390 return -1;
4391 }
4392 } else {
4393 // First... there is no target package, so can anyone access it?
4394 boolean allowed = pi.exported;
4395 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4396 if (pi.readPermission != null) {
4397 allowed = false;
4398 }
4399 }
4400 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4401 if (pi.writePermission != null) {
4402 allowed = false;
4403 }
4404 }
4405 if (allowed) {
4406 return -1;
4407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004408 }
4409
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004410 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004411 if (!pi.grantUriPermissions) {
4412 throw new SecurityException("Provider " + pi.packageName
4413 + "/" + pi.name
4414 + " does not allow granting of Uri permissions (uri "
4415 + uri + ")");
4416 }
4417 if (pi.uriPermissionPatterns != null) {
4418 final int N = pi.uriPermissionPatterns.length;
4419 boolean allowed = false;
4420 for (int i=0; i<N; i++) {
4421 if (pi.uriPermissionPatterns[i] != null
4422 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4423 allowed = true;
4424 break;
4425 }
4426 }
4427 if (!allowed) {
4428 throw new SecurityException("Provider " + pi.packageName
4429 + "/" + pi.name
4430 + " does not allow granting of permission to path of Uri "
4431 + uri);
4432 }
4433 }
4434
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004435 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004437 if (callingUid != Process.myUid()) {
4438 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4439 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4440 throw new SecurityException("Uid " + callingUid
4441 + " does not have permission to uri " + uri);
4442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 }
4444 }
4445
Dianne Hackborn39792d22010-08-19 18:01:52 -07004446 return targetUid;
4447 }
4448
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004449 public int checkGrantUriPermission(int callingUid, String targetPkg,
4450 Uri uri, int modeFlags) {
4451 synchronized(this) {
4452 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4453 }
4454 }
4455
Dianne Hackborn39792d22010-08-19 18:01:52 -07004456 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4457 Uri uri, int modeFlags, UriPermissionOwner owner) {
4458 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4459 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4460 if (modeFlags == 0) {
4461 return;
4462 }
4463
4464 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 // to the uri, and the target doesn't. Let's now give this to
4466 // the target.
4467
Joe Onorato8a9b2202010-02-26 18:56:32 -08004468 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004469 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004471 HashMap<Uri, UriPermission> targetUris
4472 = mGrantedUriPermissions.get(targetUid);
4473 if (targetUris == null) {
4474 targetUris = new HashMap<Uri, UriPermission>();
4475 mGrantedUriPermissions.put(targetUid, targetUris);
4476 }
4477
4478 UriPermission perm = targetUris.get(uri);
4479 if (perm == null) {
4480 perm = new UriPermission(targetUid, uri);
4481 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004485 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486 perm.globalModeFlags |= modeFlags;
4487 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004488 perm.readOwners.add(owner);
4489 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004491 perm.writeOwners.add(owner);
4492 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 }
4494 }
4495
Dianne Hackborn39792d22010-08-19 18:01:52 -07004496 void grantUriPermissionLocked(int callingUid,
4497 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004498 if (targetPkg == null) {
4499 throw new NullPointerException("targetPkg");
4500 }
4501
Dianne Hackborn39792d22010-08-19 18:01:52 -07004502 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4503 if (targetUid < 0) {
4504 return;
4505 }
4506
4507 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4508 }
4509
4510 /**
4511 * Like checkGrantUriPermissionLocked, but takes an Intent.
4512 */
4513 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4514 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004515 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004516 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004517 + " from " + intent + "; flags=0x"
4518 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4519
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004520 if (targetPkg == null) {
4521 throw new NullPointerException("targetPkg");
4522 }
4523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004525 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004526 }
4527 Uri data = intent.getData();
4528 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004529 return -1;
4530 }
4531 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4532 intent.getFlags());
4533 }
4534
4535 /**
4536 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4537 */
4538 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4539 String targetPkg, Intent intent, UriPermissionOwner owner) {
4540 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4541 intent.getFlags(), owner);
4542 }
4543
4544 void grantUriPermissionFromIntentLocked(int callingUid,
4545 String targetPkg, Intent intent, UriPermissionOwner owner) {
4546 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4547 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004548 return;
4549 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004550
4551 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004552 }
4553
4554 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4555 Uri uri, int modeFlags) {
4556 synchronized(this) {
4557 final ProcessRecord r = getRecordForAppLocked(caller);
4558 if (r == null) {
4559 throw new SecurityException("Unable to find app for caller "
4560 + caller
4561 + " when granting permission to uri " + uri);
4562 }
4563 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004564 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565 }
4566 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004567 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 }
4569
4570 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4571 null);
4572 }
4573 }
4574
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004575 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4577 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4578 HashMap<Uri, UriPermission> perms
4579 = mGrantedUriPermissions.get(perm.uid);
4580 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004581 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004582 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004583 perms.remove(perm.uri);
4584 if (perms.size() == 0) {
4585 mGrantedUriPermissions.remove(perm.uid);
4586 }
4587 }
4588 }
4589 }
4590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004591 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4592 int modeFlags) {
4593 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4594 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4595 if (modeFlags == 0) {
4596 return;
4597 }
4598
Joe Onorato8a9b2202010-02-26 18:56:32 -08004599 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004600 "Revoking all granted permissions to " + uri);
4601
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004602 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603
4604 final String authority = uri.getAuthority();
4605 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004606 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 if (cpr != null) {
4608 pi = cpr.info;
4609 } else {
4610 try {
4611 pi = pm.resolveContentProvider(authority,
4612 PackageManager.GET_URI_PERMISSION_PATTERNS);
4613 } catch (RemoteException ex) {
4614 }
4615 }
4616 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004617 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 return;
4619 }
4620
4621 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004622 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 // Right now, if you are not the original owner of the permission,
4624 // you are not allowed to revoke it.
4625 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4626 throw new SecurityException("Uid " + callingUid
4627 + " does not have permission to uri " + uri);
4628 //}
4629 }
4630
4631 // Go through all of the permissions and remove any that match.
4632 final List<String> SEGMENTS = uri.getPathSegments();
4633 if (SEGMENTS != null) {
4634 final int NS = SEGMENTS.size();
4635 int N = mGrantedUriPermissions.size();
4636 for (int i=0; i<N; i++) {
4637 HashMap<Uri, UriPermission> perms
4638 = mGrantedUriPermissions.valueAt(i);
4639 Iterator<UriPermission> it = perms.values().iterator();
4640 toploop:
4641 while (it.hasNext()) {
4642 UriPermission perm = it.next();
4643 Uri targetUri = perm.uri;
4644 if (!authority.equals(targetUri.getAuthority())) {
4645 continue;
4646 }
4647 List<String> targetSegments = targetUri.getPathSegments();
4648 if (targetSegments == null) {
4649 continue;
4650 }
4651 if (targetSegments.size() < NS) {
4652 continue;
4653 }
4654 for (int j=0; j<NS; j++) {
4655 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4656 continue toploop;
4657 }
4658 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004659 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004660 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004661 perm.clearModes(modeFlags);
4662 if (perm.modeFlags == 0) {
4663 it.remove();
4664 }
4665 }
4666 if (perms.size() == 0) {
4667 mGrantedUriPermissions.remove(
4668 mGrantedUriPermissions.keyAt(i));
4669 N--;
4670 i--;
4671 }
4672 }
4673 }
4674 }
4675
4676 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4677 int modeFlags) {
4678 synchronized(this) {
4679 final ProcessRecord r = getRecordForAppLocked(caller);
4680 if (r == null) {
4681 throw new SecurityException("Unable to find app for caller "
4682 + caller
4683 + " when revoking permission to uri " + uri);
4684 }
4685 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004686 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004687 return;
4688 }
4689
4690 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4691 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4692 if (modeFlags == 0) {
4693 return;
4694 }
4695
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004696 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697
4698 final String authority = uri.getAuthority();
4699 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004700 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004701 if (cpr != null) {
4702 pi = cpr.info;
4703 } else {
4704 try {
4705 pi = pm.resolveContentProvider(authority,
4706 PackageManager.GET_URI_PERMISSION_PATTERNS);
4707 } catch (RemoteException ex) {
4708 }
4709 }
4710 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004711 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 return;
4713 }
4714
4715 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4716 }
4717 }
4718
Dianne Hackborn7e269642010-08-25 19:50:20 -07004719 @Override
4720 public IBinder newUriPermissionOwner(String name) {
4721 synchronized(this) {
4722 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4723 return owner.getExternalTokenLocked();
4724 }
4725 }
4726
4727 @Override
4728 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4729 Uri uri, int modeFlags) {
4730 synchronized(this) {
4731 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4732 if (owner == null) {
4733 throw new IllegalArgumentException("Unknown owner: " + token);
4734 }
4735 if (fromUid != Binder.getCallingUid()) {
4736 if (Binder.getCallingUid() != Process.myUid()) {
4737 // Only system code can grant URI permissions on behalf
4738 // of other users.
4739 throw new SecurityException("nice try");
4740 }
4741 }
4742 if (targetPkg == null) {
4743 throw new IllegalArgumentException("null target");
4744 }
4745 if (uri == null) {
4746 throw new IllegalArgumentException("null uri");
4747 }
4748
4749 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4750 }
4751 }
4752
4753 @Override
4754 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4755 synchronized(this) {
4756 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4757 if (owner == null) {
4758 throw new IllegalArgumentException("Unknown owner: " + token);
4759 }
4760
4761 if (uri == null) {
4762 owner.removeUriPermissionsLocked(mode);
4763 } else {
4764 owner.removeUriPermissionLocked(uri, mode);
4765 }
4766 }
4767 }
4768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004769 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4770 synchronized (this) {
4771 ProcessRecord app =
4772 who != null ? getRecordForAppLocked(who) : null;
4773 if (app == null) return;
4774
4775 Message msg = Message.obtain();
4776 msg.what = WAIT_FOR_DEBUGGER_MSG;
4777 msg.obj = app;
4778 msg.arg1 = waiting ? 1 : 0;
4779 mHandler.sendMessage(msg);
4780 }
4781 }
4782
4783 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4784 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004785 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004786 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004787 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 }
4789
4790 // =========================================================
4791 // TASK MANAGEMENT
4792 // =========================================================
4793
4794 public List getTasks(int maxNum, int flags,
4795 IThumbnailReceiver receiver) {
4796 ArrayList list = new ArrayList();
4797
4798 PendingThumbnailsRecord pending = null;
4799 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004800 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004801
4802 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004803 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004804 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4805 + ", receiver=" + receiver);
4806
4807 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4808 != PackageManager.PERMISSION_GRANTED) {
4809 if (receiver != null) {
4810 // If the caller wants to wait for pending thumbnails,
4811 // it ain't gonna get them.
4812 try {
4813 receiver.finished();
4814 } catch (RemoteException ex) {
4815 }
4816 }
4817 String msg = "Permission Denial: getTasks() from pid="
4818 + Binder.getCallingPid()
4819 + ", uid=" + Binder.getCallingUid()
4820 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004821 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004822 throw new SecurityException(msg);
4823 }
4824
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004825 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004826 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004827 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004828 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004829 CharSequence topDescription = null;
4830 TaskRecord curTask = null;
4831 int numActivities = 0;
4832 int numRunning = 0;
4833 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004834 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004836 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004837
4838 // Initialize state for next task if needed.
4839 if (top == null ||
4840 (top.state == ActivityState.INITIALIZING
4841 && top.task == r.task)) {
4842 top = r;
4843 topDescription = r.description;
4844 curTask = r.task;
4845 numActivities = numRunning = 0;
4846 }
4847
4848 // Add 'r' into the current task.
4849 numActivities++;
4850 if (r.app != null && r.app.thread != null) {
4851 numRunning++;
4852 }
4853 if (topDescription == null) {
4854 topDescription = r.description;
4855 }
4856
Joe Onorato8a9b2202010-02-26 18:56:32 -08004857 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 TAG, r.intent.getComponent().flattenToShortString()
4859 + ": task=" + r.task);
4860
4861 // If the next one is a different task, generate a new
4862 // TaskInfo entry for what we have.
4863 if (next == null || next.task != curTask) {
4864 ActivityManager.RunningTaskInfo ci
4865 = new ActivityManager.RunningTaskInfo();
4866 ci.id = curTask.taskId;
4867 ci.baseActivity = r.intent.getComponent();
4868 ci.topActivity = top.intent.getComponent();
4869 ci.thumbnail = top.thumbnail;
4870 ci.description = topDescription;
4871 ci.numActivities = numActivities;
4872 ci.numRunning = numRunning;
4873 //System.out.println(
4874 // "#" + maxNum + ": " + " descr=" + ci.description);
4875 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004876 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004877 TAG, "State=" + top.state + "Idle=" + top.idle
4878 + " app=" + top.app
4879 + " thr=" + (top.app != null ? top.app.thread : null));
4880 if (top.state == ActivityState.RESUMED
4881 || top.state == ActivityState.PAUSING) {
4882 if (top.idle && top.app != null
4883 && top.app.thread != null) {
4884 topRecord = top;
4885 topThumbnail = top.app.thread;
4886 } else {
4887 top.thumbnailNeeded = true;
4888 }
4889 }
4890 if (pending == null) {
4891 pending = new PendingThumbnailsRecord(receiver);
4892 }
4893 pending.pendingRecords.add(top);
4894 }
4895 list.add(ci);
4896 maxNum--;
4897 top = null;
4898 }
4899 }
4900
4901 if (pending != null) {
4902 mPendingThumbnails.add(pending);
4903 }
4904 }
4905
Joe Onorato8a9b2202010-02-26 18:56:32 -08004906 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004907
4908 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004909 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004910 try {
4911 topThumbnail.requestThumbnail(topRecord);
4912 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004913 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004914 sendPendingThumbnail(null, topRecord, null, null, true);
4915 }
4916 }
4917
4918 if (pending == null && receiver != null) {
4919 // In this case all thumbnails were available and the client
4920 // is being asked to be told when the remaining ones come in...
4921 // which is unusually, since the top-most currently running
4922 // activity should never have a canned thumbnail! Oh well.
4923 try {
4924 receiver.finished();
4925 } catch (RemoteException ex) {
4926 }
4927 }
4928
4929 return list;
4930 }
4931
4932 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4933 int flags) {
4934 synchronized (this) {
4935 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4936 "getRecentTasks()");
4937
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004938 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004940 final int N = mRecentTasks.size();
4941 ArrayList<ActivityManager.RecentTaskInfo> res
4942 = new ArrayList<ActivityManager.RecentTaskInfo>(
4943 maxNum < N ? maxNum : N);
4944 for (int i=0; i<N && maxNum > 0; i++) {
4945 TaskRecord tr = mRecentTasks.get(i);
4946 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4947 || (tr.intent == null)
4948 || ((tr.intent.getFlags()
4949 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4950 ActivityManager.RecentTaskInfo rti
4951 = new ActivityManager.RecentTaskInfo();
4952 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4953 rti.baseIntent = new Intent(
4954 tr.intent != null ? tr.intent : tr.affinityIntent);
4955 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004956
4957 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4958 // Check whether this activity is currently available.
4959 try {
4960 if (rti.origActivity != null) {
4961 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4962 continue;
4963 }
4964 } else if (rti.baseIntent != null) {
4965 if (pm.queryIntentActivities(rti.baseIntent,
4966 null, 0) == null) {
4967 continue;
4968 }
4969 }
4970 } catch (RemoteException e) {
4971 // Will never happen.
4972 }
4973 }
4974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004975 res.add(rti);
4976 maxNum--;
4977 }
4978 }
4979 return res;
4980 }
4981 }
4982
4983 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4984 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004985 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 TaskRecord jt = startTask;
4987
4988 // First look backwards
4989 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004990 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004991 if (r.task != jt) {
4992 jt = r.task;
4993 if (affinity.equals(jt.affinity)) {
4994 return j;
4995 }
4996 }
4997 }
4998
4999 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005000 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005001 jt = startTask;
5002 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005003 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005004 if (r.task != jt) {
5005 if (affinity.equals(jt.affinity)) {
5006 return j;
5007 }
5008 jt = r.task;
5009 }
5010 }
5011
5012 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005013 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 return N-1;
5015 }
5016
5017 return -1;
5018 }
5019
5020 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005021 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005022 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005023 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005024 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5025 "moveTaskToFront()");
5026
5027 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005028 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5029 Binder.getCallingUid(), "Task to front")) {
5030 return;
5031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 final long origId = Binder.clearCallingIdentity();
5033 try {
5034 int N = mRecentTasks.size();
5035 for (int i=0; i<N; i++) {
5036 TaskRecord tr = mRecentTasks.get(i);
5037 if (tr.taskId == task) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005038 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5039 // Caller wants the home activity moved with it. To accomplish this,
5040 // we'll just move the home task to the top first.
5041 mMainStack.moveHomeToFrontLocked();
5042 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005043 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005044 return;
5045 }
5046 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005047 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5048 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 if (hr.task.taskId == task) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005050 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5051 // Caller wants the home activity moved with it. To accomplish this,
5052 // we'll just move the home task to the top first.
5053 mMainStack.moveHomeToFrontLocked();
5054 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005055 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056 return;
5057 }
5058 }
5059 } finally {
5060 Binder.restoreCallingIdentity(origId);
5061 }
5062 }
5063 }
5064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 public void moveTaskToBack(int task) {
5066 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5067 "moveTaskToBack()");
5068
5069 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005070 if (mMainStack.mResumedActivity != null
5071 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005072 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5073 Binder.getCallingUid(), "Task to back")) {
5074 return;
5075 }
5076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005078 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 Binder.restoreCallingIdentity(origId);
5080 }
5081 }
5082
5083 /**
5084 * Moves an activity, and all of the other activities within the same task, to the bottom
5085 * of the history stack. The activity's order within the task is unchanged.
5086 *
5087 * @param token A reference to the activity we wish to move
5088 * @param nonRoot If false then this only works if the activity is the root
5089 * of a task; if true it will work for any activity in a task.
5090 * @return Returns true if the move completed, false if not.
5091 */
5092 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5093 synchronized(this) {
5094 final long origId = Binder.clearCallingIdentity();
5095 int taskId = getTaskForActivityLocked(token, !nonRoot);
5096 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005097 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005098 }
5099 Binder.restoreCallingIdentity(origId);
5100 }
5101 return false;
5102 }
5103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005104 public void moveTaskBackwards(int task) {
5105 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5106 "moveTaskBackwards()");
5107
5108 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005109 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5110 Binder.getCallingUid(), "Task backwards")) {
5111 return;
5112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113 final long origId = Binder.clearCallingIdentity();
5114 moveTaskBackwardsLocked(task);
5115 Binder.restoreCallingIdentity(origId);
5116 }
5117 }
5118
5119 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005120 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 }
5122
5123 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5124 synchronized(this) {
5125 return getTaskForActivityLocked(token, onlyRoot);
5126 }
5127 }
5128
5129 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005130 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005131 TaskRecord lastTask = null;
5132 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005133 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134 if (r == token) {
5135 if (!onlyRoot || lastTask != r.task) {
5136 return r.task.taskId;
5137 }
5138 return -1;
5139 }
5140 lastTask = r.task;
5141 }
5142
5143 return -1;
5144 }
5145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005146 public void finishOtherInstances(IBinder token, ComponentName className) {
5147 synchronized(this) {
5148 final long origId = Binder.clearCallingIdentity();
5149
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005150 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005151 TaskRecord lastTask = null;
5152 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005153 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154 if (r.realActivity.equals(className)
5155 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005156 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005157 null, "others")) {
5158 i--;
5159 N--;
5160 }
5161 }
5162 lastTask = r.task;
5163 }
5164
5165 Binder.restoreCallingIdentity(origId);
5166 }
5167 }
5168
5169 // =========================================================
5170 // THUMBNAILS
5171 // =========================================================
5172
5173 public void reportThumbnail(IBinder token,
5174 Bitmap thumbnail, CharSequence description) {
5175 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5176 final long origId = Binder.clearCallingIdentity();
5177 sendPendingThumbnail(null, token, thumbnail, description, true);
5178 Binder.restoreCallingIdentity(origId);
5179 }
5180
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005181 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005182 Bitmap thumbnail, CharSequence description, boolean always) {
5183 TaskRecord task = null;
5184 ArrayList receivers = null;
5185
5186 //System.out.println("Send pending thumbnail: " + r);
5187
5188 synchronized(this) {
5189 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005190 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 if (index < 0) {
5192 return;
5193 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005194 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 }
5196 if (thumbnail == null) {
5197 thumbnail = r.thumbnail;
5198 description = r.description;
5199 }
5200 if (thumbnail == null && !always) {
5201 // If there is no thumbnail, and this entry is not actually
5202 // going away, then abort for now and pick up the next
5203 // thumbnail we get.
5204 return;
5205 }
5206 task = r.task;
5207
5208 int N = mPendingThumbnails.size();
5209 int i=0;
5210 while (i<N) {
5211 PendingThumbnailsRecord pr =
5212 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5213 //System.out.println("Looking in " + pr.pendingRecords);
5214 if (pr.pendingRecords.remove(r)) {
5215 if (receivers == null) {
5216 receivers = new ArrayList();
5217 }
5218 receivers.add(pr);
5219 if (pr.pendingRecords.size() == 0) {
5220 pr.finished = true;
5221 mPendingThumbnails.remove(i);
5222 N--;
5223 continue;
5224 }
5225 }
5226 i++;
5227 }
5228 }
5229
5230 if (receivers != null) {
5231 final int N = receivers.size();
5232 for (int i=0; i<N; i++) {
5233 try {
5234 PendingThumbnailsRecord pr =
5235 (PendingThumbnailsRecord)receivers.get(i);
5236 pr.receiver.newThumbnail(
5237 task != null ? task.taskId : -1, thumbnail, description);
5238 if (pr.finished) {
5239 pr.receiver.finished();
5240 }
5241 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005242 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 }
5244 }
5245 }
5246 }
5247
5248 // =========================================================
5249 // CONTENT PROVIDERS
5250 // =========================================================
5251
5252 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5253 List providers = null;
5254 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005255 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005257 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005258 } catch (RemoteException ex) {
5259 }
5260 if (providers != null) {
5261 final int N = providers.size();
5262 for (int i=0; i<N; i++) {
5263 ProviderInfo cpi =
5264 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005265 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 if (cpr == null) {
5267 cpr = new ContentProviderRecord(cpi, app.info);
5268 mProvidersByClass.put(cpi.name, cpr);
5269 }
5270 app.pubProviders.put(cpi.name, cpr);
5271 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005272 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005273 }
5274 }
5275 return providers;
5276 }
5277
5278 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005279 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5281 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5282 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5283 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005284 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005285 return null;
5286 }
5287 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5288 cpi.exported ? -1 : cpi.applicationInfo.uid)
5289 == PackageManager.PERMISSION_GRANTED) {
5290 return null;
5291 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005292
5293 PathPermission[] pps = cpi.pathPermissions;
5294 if (pps != null) {
5295 int i = pps.length;
5296 while (i > 0) {
5297 i--;
5298 PathPermission pp = pps[i];
5299 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5300 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005301 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005302 return null;
5303 }
5304 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5305 cpi.exported ? -1 : cpi.applicationInfo.uid)
5306 == PackageManager.PERMISSION_GRANTED) {
5307 return null;
5308 }
5309 }
5310 }
5311
Dianne Hackbornb424b632010-08-18 15:59:05 -07005312 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5313 if (perms != null) {
5314 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5315 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5316 return null;
5317 }
5318 }
5319 }
5320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 String msg = "Permission Denial: opening provider " + cpi.name
5322 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5323 + ", uid=" + callingUid + ") requires "
5324 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005325 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 return msg;
5327 }
5328
5329 private final ContentProviderHolder getContentProviderImpl(
5330 IApplicationThread caller, String name) {
5331 ContentProviderRecord cpr;
5332 ProviderInfo cpi = null;
5333
5334 synchronized(this) {
5335 ProcessRecord r = null;
5336 if (caller != null) {
5337 r = getRecordForAppLocked(caller);
5338 if (r == null) {
5339 throw new SecurityException(
5340 "Unable to find app for caller " + caller
5341 + " (pid=" + Binder.getCallingPid()
5342 + ") when getting content provider " + name);
5343 }
5344 }
5345
5346 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005347 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005348 if (cpr != null) {
5349 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005350 String msg;
5351 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5352 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 }
5354
5355 if (r != null && cpr.canRunHere(r)) {
5356 // This provider has been published or is in the process
5357 // of being published... but it is also allowed to run
5358 // in the caller's process, so don't make a connection
5359 // and just let the caller instantiate its own instance.
5360 if (cpr.provider != null) {
5361 // don't give caller the provider object, it needs
5362 // to make its own.
5363 cpr = new ContentProviderRecord(cpr);
5364 }
5365 return cpr;
5366 }
5367
5368 final long origId = Binder.clearCallingIdentity();
5369
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005370 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005371 // return it right away.
5372 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005373 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005374 "Adding provider requested by "
5375 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005376 + cpr.info.processName);
5377 Integer cnt = r.conProviders.get(cpr);
5378 if (cnt == null) {
5379 r.conProviders.put(cpr, new Integer(1));
5380 } else {
5381 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005383 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005384 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5385 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005386 // make sure to count it as being accessed and thus
5387 // back up on the LRU list. This is good because
5388 // content providers are often expensive to start.
5389 updateLruProcessLocked(cpr.app, false, true);
5390 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005391 } else {
5392 cpr.externals++;
5393 }
5394
5395 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 updateOomAdjLocked(cpr.app);
5397 }
5398
5399 Binder.restoreCallingIdentity(origId);
5400
5401 } else {
5402 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005403 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005404 resolveContentProvider(name,
5405 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005406 } catch (RemoteException ex) {
5407 }
5408 if (cpi == null) {
5409 return null;
5410 }
5411
Dianne Hackbornb424b632010-08-18 15:59:05 -07005412 String msg;
5413 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5414 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005415 }
5416
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005417 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005418 && !cpi.processName.equals("system")) {
5419 // If this content provider does not run in the system
5420 // process, and the system is not yet ready to run other
5421 // processes, then fail fast instead of hanging.
5422 throw new IllegalArgumentException(
5423 "Attempt to launch content provider before system ready");
5424 }
5425
Dianne Hackborn860755f2010-06-03 18:47:52 -07005426 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 final boolean firstClass = cpr == null;
5428 if (firstClass) {
5429 try {
5430 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005431 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005432 getApplicationInfo(
5433 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005434 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005435 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005436 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005437 + cpi.name);
5438 return null;
5439 }
5440 cpr = new ContentProviderRecord(cpi, ai);
5441 } catch (RemoteException ex) {
5442 // pm is in same process, this will never happen.
5443 }
5444 }
5445
5446 if (r != null && cpr.canRunHere(r)) {
5447 // If this is a multiprocess provider, then just return its
5448 // info and allow the caller to instantiate it. Only do
5449 // this if the provider is the same user as the caller's
5450 // process, or can run as root (so can be in any process).
5451 return cpr;
5452 }
5453
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005454 if (DEBUG_PROVIDER) {
5455 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005456 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005457 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005458 }
5459
5460 // This is single process, and our app is now connecting to it.
5461 // See if we are already in the process of launching this
5462 // provider.
5463 final int N = mLaunchingProviders.size();
5464 int i;
5465 for (i=0; i<N; i++) {
5466 if (mLaunchingProviders.get(i) == cpr) {
5467 break;
5468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 }
5470
5471 // If the provider is not already being launched, then get it
5472 // started.
5473 if (i >= N) {
5474 final long origId = Binder.clearCallingIdentity();
5475 ProcessRecord proc = startProcessLocked(cpi.processName,
5476 cpr.appInfo, false, 0, "content provider",
5477 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005478 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005480 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005481 + cpi.applicationInfo.packageName + "/"
5482 + cpi.applicationInfo.uid + " for provider "
5483 + name + ": process is bad");
5484 return null;
5485 }
5486 cpr.launchingApp = proc;
5487 mLaunchingProviders.add(cpr);
5488 Binder.restoreCallingIdentity(origId);
5489 }
5490
5491 // Make sure the provider is published (the same provider class
5492 // may be published under multiple names).
5493 if (firstClass) {
5494 mProvidersByClass.put(cpi.name, cpr);
5495 }
5496 mProvidersByName.put(name, cpr);
5497
5498 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005499 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005500 "Adding provider requested by "
5501 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005502 + cpr.info.processName);
5503 Integer cnt = r.conProviders.get(cpr);
5504 if (cnt == null) {
5505 r.conProviders.put(cpr, new Integer(1));
5506 } else {
5507 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 cpr.clients.add(r);
5510 } else {
5511 cpr.externals++;
5512 }
5513 }
5514 }
5515
5516 // Wait for the provider to be published...
5517 synchronized (cpr) {
5518 while (cpr.provider == null) {
5519 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005520 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521 + cpi.applicationInfo.packageName + "/"
5522 + cpi.applicationInfo.uid + " for provider "
5523 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005524 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005525 cpi.applicationInfo.packageName,
5526 cpi.applicationInfo.uid, name);
5527 return null;
5528 }
5529 try {
5530 cpr.wait();
5531 } catch (InterruptedException ex) {
5532 }
5533 }
5534 }
5535 return cpr;
5536 }
5537
5538 public final ContentProviderHolder getContentProvider(
5539 IApplicationThread caller, String name) {
5540 if (caller == null) {
5541 String msg = "null IApplicationThread when getting content provider "
5542 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005543 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 throw new SecurityException(msg);
5545 }
5546
5547 return getContentProviderImpl(caller, name);
5548 }
5549
5550 private ContentProviderHolder getContentProviderExternal(String name) {
5551 return getContentProviderImpl(null, name);
5552 }
5553
5554 /**
5555 * Drop a content provider from a ProcessRecord's bookkeeping
5556 * @param cpr
5557 */
5558 public void removeContentProvider(IApplicationThread caller, String name) {
5559 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005560 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005561 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005562 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005563 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005564 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 return;
5566 }
5567 final ProcessRecord r = getRecordForAppLocked(caller);
5568 if (r == null) {
5569 throw new SecurityException(
5570 "Unable to find app for caller " + caller +
5571 " when removing content provider " + name);
5572 }
5573 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005574 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005575 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005576 + r.info.processName + " from process "
5577 + localCpr.appInfo.processName);
5578 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005579 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005580 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005581 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005582 return;
5583 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005584 Integer cnt = r.conProviders.get(localCpr);
5585 if (cnt == null || cnt.intValue() <= 1) {
5586 localCpr.clients.remove(r);
5587 r.conProviders.remove(localCpr);
5588 } else {
5589 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005591 }
5592 updateOomAdjLocked();
5593 }
5594 }
5595
5596 private void removeContentProviderExternal(String name) {
5597 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005598 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005599 if(cpr == null) {
5600 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005601 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005602 return;
5603 }
5604
5605 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005606 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005607 localCpr.externals--;
5608 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005609 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005610 }
5611 updateOomAdjLocked();
5612 }
5613 }
5614
5615 public final void publishContentProviders(IApplicationThread caller,
5616 List<ContentProviderHolder> providers) {
5617 if (providers == null) {
5618 return;
5619 }
5620
5621 synchronized(this) {
5622 final ProcessRecord r = getRecordForAppLocked(caller);
5623 if (r == null) {
5624 throw new SecurityException(
5625 "Unable to find app for caller " + caller
5626 + " (pid=" + Binder.getCallingPid()
5627 + ") when publishing content providers");
5628 }
5629
5630 final long origId = Binder.clearCallingIdentity();
5631
5632 final int N = providers.size();
5633 for (int i=0; i<N; i++) {
5634 ContentProviderHolder src = providers.get(i);
5635 if (src == null || src.info == null || src.provider == null) {
5636 continue;
5637 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005638 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005639 if (dst != null) {
5640 mProvidersByClass.put(dst.info.name, dst);
5641 String names[] = dst.info.authority.split(";");
5642 for (int j = 0; j < names.length; j++) {
5643 mProvidersByName.put(names[j], dst);
5644 }
5645
5646 int NL = mLaunchingProviders.size();
5647 int j;
5648 for (j=0; j<NL; j++) {
5649 if (mLaunchingProviders.get(j) == dst) {
5650 mLaunchingProviders.remove(j);
5651 j--;
5652 NL--;
5653 }
5654 }
5655 synchronized (dst) {
5656 dst.provider = src.provider;
5657 dst.app = r;
5658 dst.notifyAll();
5659 }
5660 updateOomAdjLocked(r);
5661 }
5662 }
5663
5664 Binder.restoreCallingIdentity(origId);
5665 }
5666 }
5667
5668 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005669 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005670 synchronized (mSelf) {
5671 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5672 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005673 if (providers != null) {
5674 for (int i=providers.size()-1; i>=0; i--) {
5675 ProviderInfo pi = (ProviderInfo)providers.get(i);
5676 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5677 Slog.w(TAG, "Not installing system proc provider " + pi.name
5678 + ": not system .apk");
5679 providers.remove(i);
5680 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005681 }
5682 }
5683 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005684 if (providers != null) {
5685 mSystemThread.installSystemProviders(providers);
5686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005687 }
5688
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005689 /**
5690 * Allows app to retrieve the MIME type of a URI without having permission
5691 * to access its content provider.
5692 *
5693 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5694 *
5695 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5696 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5697 */
5698 public String getProviderMimeType(Uri uri) {
5699 final String name = uri.getAuthority();
5700 final long ident = Binder.clearCallingIdentity();
5701 ContentProviderHolder holder = null;
5702
5703 try {
5704 holder = getContentProviderExternal(name);
5705 if (holder != null) {
5706 return holder.provider.getType(uri);
5707 }
5708 } catch (RemoteException e) {
5709 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5710 return null;
5711 } finally {
5712 if (holder != null) {
5713 removeContentProviderExternal(name);
5714 }
5715 Binder.restoreCallingIdentity(ident);
5716 }
5717
5718 return null;
5719 }
5720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005721 // =========================================================
5722 // GLOBAL MANAGEMENT
5723 // =========================================================
5724
5725 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5726 ApplicationInfo info, String customProcess) {
5727 String proc = customProcess != null ? customProcess : info.processName;
5728 BatteryStatsImpl.Uid.Proc ps = null;
5729 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5730 synchronized (stats) {
5731 ps = stats.getProcessStatsLocked(info.uid, proc);
5732 }
5733 return new ProcessRecord(ps, thread, info, proc);
5734 }
5735
5736 final ProcessRecord addAppLocked(ApplicationInfo info) {
5737 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5738
5739 if (app == null) {
5740 app = newProcessRecordLocked(null, info, null);
5741 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005742 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005743 }
5744
5745 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5746 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5747 app.persistent = true;
5748 app.maxAdj = CORE_SERVER_ADJ;
5749 }
5750 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5751 mPersistentStartingProcesses.add(app);
5752 startProcessLocked(app, "added application", app.processName);
5753 }
5754
5755 return app;
5756 }
5757
5758 public void unhandledBack() {
5759 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5760 "unhandledBack()");
5761
5762 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005763 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005764 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 TAG, "Performing unhandledBack(): stack size = " + count);
5766 if (count > 1) {
5767 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005768 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005769 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5770 Binder.restoreCallingIdentity(origId);
5771 }
5772 }
5773 }
5774
5775 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5776 String name = uri.getAuthority();
5777 ContentProviderHolder cph = getContentProviderExternal(name);
5778 ParcelFileDescriptor pfd = null;
5779 if (cph != null) {
5780 // We record the binder invoker's uid in thread-local storage before
5781 // going to the content provider to open the file. Later, in the code
5782 // that handles all permissions checks, we look for this uid and use
5783 // that rather than the Activity Manager's own uid. The effect is that
5784 // we do the check against the caller's permissions even though it looks
5785 // to the content provider like the Activity Manager itself is making
5786 // the request.
5787 sCallerIdentity.set(new Identity(
5788 Binder.getCallingPid(), Binder.getCallingUid()));
5789 try {
5790 pfd = cph.provider.openFile(uri, "r");
5791 } catch (FileNotFoundException e) {
5792 // do nothing; pfd will be returned null
5793 } finally {
5794 // Ensure that whatever happens, we clean up the identity state
5795 sCallerIdentity.remove();
5796 }
5797
5798 // We've got the fd now, so we're done with the provider.
5799 removeContentProviderExternal(name);
5800 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005801 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005802 }
5803 return pfd;
5804 }
5805
5806 public void goingToSleep() {
5807 synchronized(this) {
5808 mSleeping = true;
5809 mWindowManager.setEventDispatching(false);
5810
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005811 if (mMainStack.mResumedActivity != null) {
5812 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005813 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005814 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005815 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005816
5817 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005818 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005819 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5820 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005821 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005822 }
5823 }
5824
Dianne Hackborn55280a92009-05-07 15:53:46 -07005825 public boolean shutdown(int timeout) {
5826 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5827 != PackageManager.PERMISSION_GRANTED) {
5828 throw new SecurityException("Requires permission "
5829 + android.Manifest.permission.SHUTDOWN);
5830 }
5831
5832 boolean timedout = false;
5833
5834 synchronized(this) {
5835 mShuttingDown = true;
5836 mWindowManager.setEventDispatching(false);
5837
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005838 if (mMainStack.mResumedActivity != null) {
5839 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005840 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005841 while (mMainStack.mResumedActivity != null
5842 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005843 long delay = endTime - System.currentTimeMillis();
5844 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005845 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005846 timedout = true;
5847 break;
5848 }
5849 try {
5850 this.wait();
5851 } catch (InterruptedException e) {
5852 }
5853 }
5854 }
5855 }
5856
5857 mUsageStatsService.shutdown();
5858 mBatteryStatsService.shutdown();
5859
5860 return timedout;
5861 }
5862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 public void wakingUp() {
5864 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005865 if (mMainStack.mGoingToSleep.isHeld()) {
5866 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005867 }
5868 mWindowManager.setEventDispatching(true);
5869 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005870 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005871 }
5872 }
5873
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005874 public void stopAppSwitches() {
5875 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5876 != PackageManager.PERMISSION_GRANTED) {
5877 throw new SecurityException("Requires permission "
5878 + android.Manifest.permission.STOP_APP_SWITCHES);
5879 }
5880
5881 synchronized(this) {
5882 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5883 + APP_SWITCH_DELAY_TIME;
5884 mDidAppSwitch = false;
5885 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5886 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5887 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5888 }
5889 }
5890
5891 public void resumeAppSwitches() {
5892 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5893 != PackageManager.PERMISSION_GRANTED) {
5894 throw new SecurityException("Requires permission "
5895 + android.Manifest.permission.STOP_APP_SWITCHES);
5896 }
5897
5898 synchronized(this) {
5899 // Note that we don't execute any pending app switches... we will
5900 // let those wait until either the timeout, or the next start
5901 // activity request.
5902 mAppSwitchesAllowedTime = 0;
5903 }
5904 }
5905
5906 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5907 String name) {
5908 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5909 return true;
5910 }
5911
5912 final int perm = checkComponentPermission(
5913 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5914 callingUid, -1);
5915 if (perm == PackageManager.PERMISSION_GRANTED) {
5916 return true;
5917 }
5918
Joe Onorato8a9b2202010-02-26 18:56:32 -08005919 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005920 return false;
5921 }
5922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005923 public void setDebugApp(String packageName, boolean waitForDebugger,
5924 boolean persistent) {
5925 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5926 "setDebugApp()");
5927
5928 // Note that this is not really thread safe if there are multiple
5929 // callers into it at the same time, but that's not a situation we
5930 // care about.
5931 if (persistent) {
5932 final ContentResolver resolver = mContext.getContentResolver();
5933 Settings.System.putString(
5934 resolver, Settings.System.DEBUG_APP,
5935 packageName);
5936 Settings.System.putInt(
5937 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5938 waitForDebugger ? 1 : 0);
5939 }
5940
5941 synchronized (this) {
5942 if (!persistent) {
5943 mOrigDebugApp = mDebugApp;
5944 mOrigWaitForDebugger = mWaitForDebugger;
5945 }
5946 mDebugApp = packageName;
5947 mWaitForDebugger = waitForDebugger;
5948 mDebugTransient = !persistent;
5949 if (packageName != null) {
5950 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005951 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005952 Binder.restoreCallingIdentity(origId);
5953 }
5954 }
5955 }
5956
5957 public void setAlwaysFinish(boolean enabled) {
5958 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5959 "setAlwaysFinish()");
5960
5961 Settings.System.putInt(
5962 mContext.getContentResolver(),
5963 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5964
5965 synchronized (this) {
5966 mAlwaysFinishActivities = enabled;
5967 }
5968 }
5969
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005970 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005971 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005972 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005973 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005974 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005975 }
5976 }
5977
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005978 public boolean isUserAMonkey() {
5979 // For now the fact that there is a controller implies
5980 // we have a monkey.
5981 synchronized (this) {
5982 return mController != null;
5983 }
5984 }
5985
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005986 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005987 synchronized (this) {
5988 mWatchers.register(watcher);
5989 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005990 }
5991
5992 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005993 synchronized (this) {
5994 mWatchers.unregister(watcher);
5995 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005996 }
5997
Daniel Sandler69a48172010-06-23 16:29:36 -04005998 public void setImmersive(IBinder token, boolean immersive) {
5999 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006000 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006001 if (index < 0) {
6002 throw new IllegalArgumentException();
6003 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006004 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006005 r.immersive = immersive;
6006 }
6007 }
6008
6009 public boolean isImmersive(IBinder token) {
6010 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006011 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006012 if (index < 0) {
6013 throw new IllegalArgumentException();
6014 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006015 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006016 return r.immersive;
6017 }
6018 }
6019
6020 public boolean isTopActivityImmersive() {
6021 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006022 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006023 return (r != null) ? r.immersive : false;
6024 }
6025 }
6026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006027 public final void enterSafeMode() {
6028 synchronized(this) {
6029 // It only makes sense to do this before the system is ready
6030 // and started launching other packages.
6031 if (!mSystemReady) {
6032 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006033 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006034 } catch (RemoteException e) {
6035 }
6036
6037 View v = LayoutInflater.from(mContext).inflate(
6038 com.android.internal.R.layout.safe_mode, null);
6039 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown3b2b3542010-10-15 00:54:27 -07006040 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6042 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6043 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6044 lp.format = v.getBackground().getOpacity();
6045 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6046 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6047 ((WindowManager)mContext.getSystemService(
6048 Context.WINDOW_SERVICE)).addView(v, lp);
6049 }
6050 }
6051 }
6052
6053 public void noteWakeupAlarm(IIntentSender sender) {
6054 if (!(sender instanceof PendingIntentRecord)) {
6055 return;
6056 }
6057 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6058 synchronized (stats) {
6059 if (mBatteryStatsService.isOnBattery()) {
6060 mBatteryStatsService.enforceCallingPermission();
6061 PendingIntentRecord rec = (PendingIntentRecord)sender;
6062 int MY_UID = Binder.getCallingUid();
6063 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6064 BatteryStatsImpl.Uid.Pkg pkg =
6065 stats.getPackageStatsLocked(uid, rec.key.packageName);
6066 pkg.incWakeupsLocked();
6067 }
6068 }
6069 }
6070
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006071 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006072 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006073 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006074 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006075 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006076 // XXX Note: don't acquire main activity lock here, because the window
6077 // manager calls in with its locks held.
6078
6079 boolean killed = false;
6080 synchronized (mPidsSelfLocked) {
6081 int[] types = new int[pids.length];
6082 int worstType = 0;
6083 for (int i=0; i<pids.length; i++) {
6084 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6085 if (proc != null) {
6086 int type = proc.setAdj;
6087 types[i] = type;
6088 if (type > worstType) {
6089 worstType = type;
6090 }
6091 }
6092 }
6093
6094 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6095 // then constrain it so we will kill all hidden procs.
6096 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6097 worstType = HIDDEN_APP_MIN_ADJ;
6098 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006099 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006100 for (int i=0; i<pids.length; i++) {
6101 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6102 if (proc == null) {
6103 continue;
6104 }
6105 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006106 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006107 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006108 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6109 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006110 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006111 proc.killedBackground = true;
6112 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006113 }
6114 }
6115 }
6116 return killed;
6117 }
6118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006119 public final void startRunning(String pkg, String cls, String action,
6120 String data) {
6121 synchronized(this) {
6122 if (mStartRunning) {
6123 return;
6124 }
6125 mStartRunning = true;
6126 mTopComponent = pkg != null && cls != null
6127 ? new ComponentName(pkg, cls) : null;
6128 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6129 mTopData = data;
6130 if (!mSystemReady) {
6131 return;
6132 }
6133 }
6134
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006135 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006136 }
6137
6138 private void retrieveSettings() {
6139 final ContentResolver resolver = mContext.getContentResolver();
6140 String debugApp = Settings.System.getString(
6141 resolver, Settings.System.DEBUG_APP);
6142 boolean waitForDebugger = Settings.System.getInt(
6143 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6144 boolean alwaysFinishActivities = Settings.System.getInt(
6145 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6146
6147 Configuration configuration = new Configuration();
6148 Settings.System.getConfiguration(resolver, configuration);
6149
6150 synchronized (this) {
6151 mDebugApp = mOrigDebugApp = debugApp;
6152 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6153 mAlwaysFinishActivities = alwaysFinishActivities;
6154 // This happens before any activities are started, so we can
6155 // change mConfiguration in-place.
6156 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006157 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006158 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006159 }
6160 }
6161
6162 public boolean testIsSystemReady() {
6163 // no need to synchronize(this) just to read & return the value
6164 return mSystemReady;
6165 }
6166
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006167 private static File getCalledPreBootReceiversFile() {
6168 File dataDir = Environment.getDataDirectory();
6169 File systemDir = new File(dataDir, "system");
6170 File fname = new File(systemDir, "called_pre_boots.dat");
6171 return fname;
6172 }
6173
6174 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6175 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6176 File file = getCalledPreBootReceiversFile();
6177 FileInputStream fis = null;
6178 try {
6179 fis = new FileInputStream(file);
6180 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6181 int vers = dis.readInt();
6182 String codename = dis.readUTF();
6183 if (vers == android.os.Build.VERSION.SDK_INT
6184 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6185 int num = dis.readInt();
6186 while (num > 0) {
6187 num--;
6188 String pkg = dis.readUTF();
6189 String cls = dis.readUTF();
6190 lastDoneReceivers.add(new ComponentName(pkg, cls));
6191 }
6192 }
6193 } catch (FileNotFoundException e) {
6194 } catch (IOException e) {
6195 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6196 } finally {
6197 if (fis != null) {
6198 try {
6199 fis.close();
6200 } catch (IOException e) {
6201 }
6202 }
6203 }
6204 return lastDoneReceivers;
6205 }
6206
6207 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6208 File file = getCalledPreBootReceiversFile();
6209 FileOutputStream fos = null;
6210 DataOutputStream dos = null;
6211 try {
6212 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6213 fos = new FileOutputStream(file);
6214 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6215 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6216 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6217 dos.writeInt(list.size());
6218 for (int i=0; i<list.size(); i++) {
6219 dos.writeUTF(list.get(i).getPackageName());
6220 dos.writeUTF(list.get(i).getClassName());
6221 }
6222 } catch (IOException e) {
6223 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6224 file.delete();
6225 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006226 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006227 if (dos != null) {
6228 try {
6229 dos.close();
6230 } catch (IOException e) {
6231 // TODO Auto-generated catch block
6232 e.printStackTrace();
6233 }
6234 }
6235 }
6236 }
6237
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006238 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006239 // In the simulator, startRunning will never have been called, which
6240 // normally sets a few crucial variables. Do it here instead.
6241 if (!Process.supportsProcesses()) {
6242 mStartRunning = true;
6243 mTopAction = Intent.ACTION_MAIN;
6244 }
6245
6246 synchronized(this) {
6247 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006248 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006249 return;
6250 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006251
6252 // Check to see if there are any update receivers to run.
6253 if (!mDidUpdate) {
6254 if (mWaitingUpdate) {
6255 return;
6256 }
6257 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6258 List<ResolveInfo> ris = null;
6259 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006260 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006261 intent, null, 0);
6262 } catch (RemoteException e) {
6263 }
6264 if (ris != null) {
6265 for (int i=ris.size()-1; i>=0; i--) {
6266 if ((ris.get(i).activityInfo.applicationInfo.flags
6267 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6268 ris.remove(i);
6269 }
6270 }
6271 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006272
6273 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6274
6275 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006276 for (int i=0; i<ris.size(); i++) {
6277 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006278 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6279 if (lastDoneReceivers.contains(comp)) {
6280 ris.remove(i);
6281 i--;
6282 }
6283 }
6284
6285 for (int i=0; i<ris.size(); i++) {
6286 ActivityInfo ai = ris.get(i).activityInfo;
6287 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6288 doneReceivers.add(comp);
6289 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006290 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006291 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006292 finisher = new IIntentReceiver.Stub() {
6293 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006294 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006295 boolean sticky) {
6296 // The raw IIntentReceiver interface is called
6297 // with the AM lock held, so redispatch to
6298 // execute our code without the lock.
6299 mHandler.post(new Runnable() {
6300 public void run() {
6301 synchronized (ActivityManagerService.this) {
6302 mDidUpdate = true;
6303 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006304 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006305 systemReady(goingCallback);
6306 }
6307 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006308 }
6309 };
6310 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006311 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006312 broadcastIntentLocked(null, null, intent, null, finisher,
6313 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006314 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006315 mWaitingUpdate = true;
6316 }
6317 }
6318 }
6319 if (mWaitingUpdate) {
6320 return;
6321 }
6322 mDidUpdate = true;
6323 }
6324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006325 mSystemReady = true;
6326 if (!mStartRunning) {
6327 return;
6328 }
6329 }
6330
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006331 ArrayList<ProcessRecord> procsToKill = null;
6332 synchronized(mPidsSelfLocked) {
6333 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6334 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6335 if (!isAllowedWhileBooting(proc.info)){
6336 if (procsToKill == null) {
6337 procsToKill = new ArrayList<ProcessRecord>();
6338 }
6339 procsToKill.add(proc);
6340 }
6341 }
6342 }
6343
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006344 synchronized(this) {
6345 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006346 for (int i=procsToKill.size()-1; i>=0; i--) {
6347 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006348 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006349 removeProcessLocked(proc, true);
6350 }
6351 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006352
6353 // Now that we have cleaned up any update processes, we
6354 // are ready to start launching real processes and know that
6355 // we won't trample on them any more.
6356 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006357 }
6358
Joe Onorato8a9b2202010-02-26 18:56:32 -08006359 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006360 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006361 SystemClock.uptimeMillis());
6362
6363 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006364 // Make sure we have no pre-ready processes sitting around.
6365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006366 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6367 ResolveInfo ri = mContext.getPackageManager()
6368 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006369 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006370 CharSequence errorMsg = null;
6371 if (ri != null) {
6372 ActivityInfo ai = ri.activityInfo;
6373 ApplicationInfo app = ai.applicationInfo;
6374 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6375 mTopAction = Intent.ACTION_FACTORY_TEST;
6376 mTopData = null;
6377 mTopComponent = new ComponentName(app.packageName,
6378 ai.name);
6379 } else {
6380 errorMsg = mContext.getResources().getText(
6381 com.android.internal.R.string.factorytest_not_system);
6382 }
6383 } else {
6384 errorMsg = mContext.getResources().getText(
6385 com.android.internal.R.string.factorytest_no_action);
6386 }
6387 if (errorMsg != null) {
6388 mTopAction = null;
6389 mTopData = null;
6390 mTopComponent = null;
6391 Message msg = Message.obtain();
6392 msg.what = SHOW_FACTORY_ERROR_MSG;
6393 msg.getData().putCharSequence("msg", errorMsg);
6394 mHandler.sendMessage(msg);
6395 }
6396 }
6397 }
6398
6399 retrieveSettings();
6400
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006401 if (goingCallback != null) goingCallback.run();
6402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006403 synchronized (this) {
6404 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6405 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006406 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006407 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006408 if (apps != null) {
6409 int N = apps.size();
6410 int i;
6411 for (i=0; i<N; i++) {
6412 ApplicationInfo info
6413 = (ApplicationInfo)apps.get(i);
6414 if (info != null &&
6415 !info.packageName.equals("android")) {
6416 addAppLocked(info);
6417 }
6418 }
6419 }
6420 } catch (RemoteException ex) {
6421 // pm is in same process, this will never happen.
6422 }
6423 }
6424
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006425 // Start up initial activity.
6426 mBooting = true;
6427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006428 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006429 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006430 Message msg = Message.obtain();
6431 msg.what = SHOW_UID_ERROR_MSG;
6432 mHandler.sendMessage(msg);
6433 }
6434 } catch (RemoteException e) {
6435 }
6436
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006437 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006438 }
6439 }
6440
Dan Egnorb7f03672009-12-09 16:22:32 -08006441 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006442 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006443 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006444 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006445 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006446 startAppProblemLocked(app);
6447 app.stopFreezingAllLocked();
6448 return handleAppCrashLocked(app);
6449 }
6450
Dan Egnorb7f03672009-12-09 16:22:32 -08006451 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006452 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006453 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006454 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006455 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6456 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006457 startAppProblemLocked(app);
6458 app.stopFreezingAllLocked();
6459 }
6460
6461 /**
6462 * Generate a process error record, suitable for attachment to a ProcessRecord.
6463 *
6464 * @param app The ProcessRecord in which the error occurred.
6465 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6466 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006467 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006468 * @param shortMsg Short message describing the crash.
6469 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006470 * @param stackTrace Full crash stack trace, may be null.
6471 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006472 * @return Returns a fully-formed AppErrorStateInfo record.
6473 */
6474 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006475 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006476 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006478 report.condition = condition;
6479 report.processName = app.processName;
6480 report.pid = app.pid;
6481 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006482 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006483 report.shortMsg = shortMsg;
6484 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006485 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486
6487 return report;
6488 }
6489
Dan Egnor42471dd2010-01-07 17:25:22 -08006490 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006491 synchronized (this) {
6492 app.crashing = false;
6493 app.crashingReport = null;
6494 app.notResponding = false;
6495 app.notRespondingReport = null;
6496 if (app.anrDialog == fromDialog) {
6497 app.anrDialog = null;
6498 }
6499 if (app.waitDialog == fromDialog) {
6500 app.waitDialog = null;
6501 }
6502 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006503 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006504 Slog.i(ActivityManagerService.TAG, "Killing "
6505 + app.processName + " (pid=" + app.pid + "): user's request");
6506 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6507 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006508 Process.killProcess(app.pid);
6509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006510 }
6511 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006512
Dan Egnorb7f03672009-12-09 16:22:32 -08006513 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006514 long now = SystemClock.uptimeMillis();
6515
6516 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6517 app.info.uid);
6518 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6519 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006520 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006521 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006522 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 app.info.processName, app.info.uid);
6524 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006525 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6526 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006527 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006528 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006529 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006530 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006531 }
6532 }
6533 if (!app.persistent) {
6534 // We don't want to start this process again until the user
6535 // explicitly does so... but for persistent process, we really
6536 // need to keep it running. If a persistent process is actually
6537 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006538 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006539 app.info.processName);
6540 mBadProcesses.put(app.info.processName, app.info.uid, now);
6541 app.bad = true;
6542 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6543 app.removed = true;
6544 removeProcessLocked(app, false);
6545 return false;
6546 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006547 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006548 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006549 if (r.app == app) {
6550 // If the top running activity is from this crashing
6551 // process, then terminate it to avoid getting in a loop.
6552 Slog.w(TAG, " Force finishing activity "
6553 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006554 int index = mMainStack.indexOfTokenLocked(r);
6555 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006556 Activity.RESULT_CANCELED, null, "crashed");
6557 // Also terminate an activities below it that aren't yet
6558 // stopped, to avoid a situation where one will get
6559 // re-start our crashing activity once it gets resumed again.
6560 index--;
6561 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006562 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006563 if (r.state == ActivityState.RESUMED
6564 || r.state == ActivityState.PAUSING
6565 || r.state == ActivityState.PAUSED) {
6566 if (!r.isHomeActivity) {
6567 Slog.w(TAG, " Force finishing activity "
6568 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006569 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006570 Activity.RESULT_CANCELED, null, "crashed");
6571 }
6572 }
6573 }
6574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006575 }
6576
6577 // Bump up the crash count of any services currently running in the proc.
6578 if (app.services.size() != 0) {
6579 // Any services running in the application need to be placed
6580 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006581 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006582 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006583 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 sr.crashCount++;
6585 }
6586 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006587
6588 // If the crashing process is what we consider to be the "home process" and it has been
6589 // replaced by a third-party app, clear the package preferred activities from packages
6590 // with a home activity running in the process to prevent a repeatedly crashing app
6591 // from blocking the user to manually clear the list.
6592 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6593 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6594 Iterator it = mHomeProcess.activities.iterator();
6595 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006596 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006597 if (r.isHomeActivity) {
6598 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6599 try {
6600 ActivityThread.getPackageManager()
6601 .clearPackagePreferredActivities(r.packageName);
6602 } catch (RemoteException c) {
6603 // pm is in same process, this will never happen.
6604 }
6605 }
6606 }
6607 }
6608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006609 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6610 return true;
6611 }
6612
6613 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006614 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6615 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006616 skipCurrentReceiverLocked(app);
6617 }
6618
6619 void skipCurrentReceiverLocked(ProcessRecord app) {
6620 boolean reschedule = false;
6621 BroadcastRecord r = app.curReceiver;
6622 if (r != null) {
6623 // The current broadcast is waiting for this app's receiver
6624 // to be finished. Looks like that's not going to happen, so
6625 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006626 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006627 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6628 r.resultExtras, r.resultAbort, true);
6629 reschedule = true;
6630 }
6631 r = mPendingBroadcast;
6632 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006633 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006634 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006635 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006636 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6637 r.resultExtras, r.resultAbort, true);
6638 reschedule = true;
6639 }
6640 if (reschedule) {
6641 scheduleBroadcastsLocked();
6642 }
6643 }
6644
Dan Egnor60d87622009-12-16 16:32:58 -08006645 /**
6646 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6647 * The application process will exit immediately after this call returns.
6648 * @param app object of the crashing app, null for the system server
6649 * @param crashInfo describing the exception
6650 */
6651 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6652 ProcessRecord r = findAppProcess(app);
6653
6654 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6655 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006656 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006657 crashInfo.exceptionClassName,
6658 crashInfo.exceptionMessage,
6659 crashInfo.throwFileName,
6660 crashInfo.throwLineNumber);
6661
Dan Egnor42471dd2010-01-07 17:25:22 -08006662 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006663
6664 crashApplication(r, crashInfo);
6665 }
6666
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006667 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006668 IBinder app,
6669 int violationMask,
6670 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006671 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006672
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006673 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006674 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006675 boolean logIt = true;
6676 synchronized (mAlreadyLoggedViolatedStacks) {
6677 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6678 logIt = false;
6679 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006680 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006681 // the relative pain numbers, without logging all
6682 // the stack traces repeatedly. We'd want to do
6683 // likewise in the client code, which also does
6684 // dup suppression, before the Binder call.
6685 } else {
6686 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6687 mAlreadyLoggedViolatedStacks.clear();
6688 }
6689 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6690 }
6691 }
6692 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006693 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006694 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006695 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006696
6697 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6698 AppErrorResult result = new AppErrorResult();
6699 synchronized (this) {
6700 final long origId = Binder.clearCallingIdentity();
6701
6702 Message msg = Message.obtain();
6703 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6704 HashMap<String, Object> data = new HashMap<String, Object>();
6705 data.put("result", result);
6706 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006707 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006708 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006709 msg.obj = data;
6710 mHandler.sendMessage(msg);
6711
6712 Binder.restoreCallingIdentity(origId);
6713 }
6714 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006715 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006716 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006717 }
6718
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006719 // Depending on the policy in effect, there could be a bunch of
6720 // these in quick succession so we try to batch these together to
6721 // minimize disk writes, number of dropbox entries, and maximize
6722 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006723 private void logStrictModeViolationToDropBox(
6724 ProcessRecord process,
6725 StrictMode.ViolationInfo info) {
6726 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006727 return;
6728 }
6729 final boolean isSystemApp = process == null ||
6730 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6731 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6732 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6733 final DropBoxManager dbox = (DropBoxManager)
6734 mContext.getSystemService(Context.DROPBOX_SERVICE);
6735
6736 // Exit early if the dropbox isn't configured to accept this report type.
6737 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6738
6739 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006740 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006741 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6742 synchronized (sb) {
6743 bufferWasEmpty = sb.length() == 0;
6744 appendDropBoxProcessHeaders(process, sb);
6745 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6746 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006747 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6748 if (info.violationNumThisLoop != 0) {
6749 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6750 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006751 if (info.numAnimationsRunning != 0) {
6752 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6753 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006754 if (info.broadcastIntentAction != null) {
6755 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6756 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006757 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006758 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006759 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006760 if (info.tags != null) {
6761 for (String tag : info.tags) {
6762 sb.append("Span-Tag: ").append(tag).append("\n");
6763 }
6764 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006765 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006766 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6767 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006768 }
6769 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006770
6771 // Only buffer up to ~64k. Various logging bits truncate
6772 // things at 128k.
6773 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006774 }
6775
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006776 // Flush immediately if the buffer's grown too large, or this
6777 // is a non-system app. Non-system apps are isolated with a
6778 // different tag & policy and not batched.
6779 //
6780 // Batching is useful during internal testing with
6781 // StrictMode settings turned up high. Without batching,
6782 // thousands of separate files could be created on boot.
6783 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006784 new Thread("Error dump: " + dropboxTag) {
6785 @Override
6786 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006787 String report;
6788 synchronized (sb) {
6789 report = sb.toString();
6790 sb.delete(0, sb.length());
6791 sb.trimToSize();
6792 }
6793 if (report.length() != 0) {
6794 dbox.addText(dropboxTag, report);
6795 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006796 }
6797 }.start();
6798 return;
6799 }
6800
6801 // System app batching:
6802 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006803 // An existing dropbox-writing thread is outstanding, so
6804 // we don't need to start it up. The existing thread will
6805 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006806 return;
6807 }
6808
6809 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6810 // (After this point, we shouldn't access AMS internal data structures.)
6811 new Thread("Error dump: " + dropboxTag) {
6812 @Override
6813 public void run() {
6814 // 5 second sleep to let stacks arrive and be batched together
6815 try {
6816 Thread.sleep(5000); // 5 seconds
6817 } catch (InterruptedException e) {}
6818
6819 String errorReport;
6820 synchronized (mStrictModeBuffer) {
6821 errorReport = mStrictModeBuffer.toString();
6822 if (errorReport.length() == 0) {
6823 return;
6824 }
6825 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6826 mStrictModeBuffer.trimToSize();
6827 }
6828 dbox.addText(dropboxTag, errorReport);
6829 }
6830 }.start();
6831 }
6832
Dan Egnor60d87622009-12-16 16:32:58 -08006833 /**
6834 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6835 * @param app object of the crashing app, null for the system server
6836 * @param tag reported by the caller
6837 * @param crashInfo describing the context of the error
6838 * @return true if the process should exit immediately (WTF is fatal)
6839 */
6840 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006841 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006842 ProcessRecord r = findAppProcess(app);
6843
6844 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6845 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006846 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006847 tag, crashInfo.exceptionMessage);
6848
Dan Egnor42471dd2010-01-07 17:25:22 -08006849 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006850
Doug Zongker43866e02010-01-07 12:09:54 -08006851 if (Settings.Secure.getInt(mContext.getContentResolver(),
6852 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006853 crashApplication(r, crashInfo);
6854 return true;
6855 } else {
6856 return false;
6857 }
6858 }
6859
6860 /**
6861 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6862 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6863 */
6864 private ProcessRecord findAppProcess(IBinder app) {
6865 if (app == null) {
6866 return null;
6867 }
6868
6869 synchronized (this) {
6870 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6871 final int NA = apps.size();
6872 for (int ia=0; ia<NA; ia++) {
6873 ProcessRecord p = apps.valueAt(ia);
6874 if (p.thread != null && p.thread.asBinder() == app) {
6875 return p;
6876 }
6877 }
6878 }
6879
Joe Onorato8a9b2202010-02-26 18:56:32 -08006880 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006881 return null;
6882 }
6883 }
6884
6885 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006886 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6887 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006888 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006889 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6890 // Note: ProcessRecord 'process' is guarded by the service
6891 // instance. (notably process.pkgList, which could otherwise change
6892 // concurrently during execution of this method)
6893 synchronized (this) {
6894 if (process == null || process.pid == MY_PID) {
6895 sb.append("Process: system_server\n");
6896 } else {
6897 sb.append("Process: ").append(process.processName).append("\n");
6898 }
6899 if (process == null) {
6900 return;
6901 }
Dan Egnora455d192010-03-12 08:52:28 -08006902 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006903 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006904 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6905 for (String pkg : process.pkgList) {
6906 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006907 try {
Dan Egnora455d192010-03-12 08:52:28 -08006908 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6909 if (pi != null) {
6910 sb.append(" v").append(pi.versionCode);
6911 if (pi.versionName != null) {
6912 sb.append(" (").append(pi.versionName).append(")");
6913 }
6914 }
6915 } catch (RemoteException e) {
6916 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006917 }
Dan Egnora455d192010-03-12 08:52:28 -08006918 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006919 }
Dan Egnora455d192010-03-12 08:52:28 -08006920 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006921 }
6922
6923 private static String processClass(ProcessRecord process) {
6924 if (process == null || process.pid == MY_PID) {
6925 return "system_server";
6926 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6927 return "system_app";
6928 } else {
6929 return "data_app";
6930 }
6931 }
6932
6933 /**
6934 * Write a description of an error (crash, WTF, ANR) to the drop box.
6935 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6936 * @param process which caused the error, null means the system server
6937 * @param activity which triggered the error, null if unknown
6938 * @param parent activity related to the error, null if unknown
6939 * @param subject line related to the error, null if absent
6940 * @param report in long form describing the error, null if absent
6941 * @param logFile to include in the report, null if none
6942 * @param crashInfo giving an application stack trace, null if absent
6943 */
6944 public void addErrorToDropBox(String eventType,
6945 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6946 final String report, final File logFile,
6947 final ApplicationErrorReport.CrashInfo crashInfo) {
6948 // NOTE -- this must never acquire the ActivityManagerService lock,
6949 // otherwise the watchdog may be prevented from resetting the system.
6950
6951 final String dropboxTag = processClass(process) + "_" + eventType;
6952 final DropBoxManager dbox = (DropBoxManager)
6953 mContext.getSystemService(Context.DROPBOX_SERVICE);
6954
6955 // Exit early if the dropbox isn't configured to accept this report type.
6956 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6957
6958 final StringBuilder sb = new StringBuilder(1024);
6959 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006960 if (activity != null) {
6961 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6962 }
6963 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6964 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6965 }
6966 if (parent != null && parent != activity) {
6967 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6968 }
6969 if (subject != null) {
6970 sb.append("Subject: ").append(subject).append("\n");
6971 }
6972 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02006973 if (Debug.isDebuggerConnected()) {
6974 sb.append("Debugger: Connected\n");
6975 }
Dan Egnora455d192010-03-12 08:52:28 -08006976 sb.append("\n");
6977
6978 // Do the rest in a worker thread to avoid blocking the caller on I/O
6979 // (After this point, we shouldn't access AMS internal data structures.)
6980 Thread worker = new Thread("Error dump: " + dropboxTag) {
6981 @Override
6982 public void run() {
6983 if (report != null) {
6984 sb.append(report);
6985 }
6986 if (logFile != null) {
6987 try {
6988 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6989 } catch (IOException e) {
6990 Slog.e(TAG, "Error reading " + logFile, e);
6991 }
6992 }
6993 if (crashInfo != null && crashInfo.stackTrace != null) {
6994 sb.append(crashInfo.stackTrace);
6995 }
6996
6997 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6998 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6999 if (lines > 0) {
7000 sb.append("\n");
7001
7002 // Merge several logcat streams, and take the last N lines
7003 InputStreamReader input = null;
7004 try {
7005 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7006 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7007 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7008
7009 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7010 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7011 input = new InputStreamReader(logcat.getInputStream());
7012
7013 int num;
7014 char[] buf = new char[8192];
7015 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7016 } catch (IOException e) {
7017 Slog.e(TAG, "Error running logcat", e);
7018 } finally {
7019 if (input != null) try { input.close(); } catch (IOException e) {}
7020 }
7021 }
7022
7023 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007024 }
Dan Egnora455d192010-03-12 08:52:28 -08007025 };
7026
7027 if (process == null || process.pid == MY_PID) {
7028 worker.run(); // We may be about to die -- need to run this synchronously
7029 } else {
7030 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007031 }
7032 }
7033
7034 /**
7035 * Bring up the "unexpected error" dialog box for a crashing app.
7036 * Deal with edge cases (intercepts from instrumented applications,
7037 * ActivityController, error intent receivers, that sort of thing).
7038 * @param r the application crashing
7039 * @param crashInfo describing the failure
7040 */
7041 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007042 long timeMillis = System.currentTimeMillis();
7043 String shortMsg = crashInfo.exceptionClassName;
7044 String longMsg = crashInfo.exceptionMessage;
7045 String stackTrace = crashInfo.stackTrace;
7046 if (shortMsg != null && longMsg != null) {
7047 longMsg = shortMsg + ": " + longMsg;
7048 } else if (shortMsg != null) {
7049 longMsg = shortMsg;
7050 }
7051
Dan Egnor60d87622009-12-16 16:32:58 -08007052 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007053 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007054 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007055 try {
7056 String name = r != null ? r.processName : null;
7057 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007058 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007059 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007060 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007061 + " at watcher's request");
7062 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007063 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007064 }
7065 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007066 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007067 }
7068 }
7069
7070 final long origId = Binder.clearCallingIdentity();
7071
7072 // If this process is running instrumentation, finish it.
7073 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007074 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007075 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007076 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7077 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007078 Bundle info = new Bundle();
7079 info.putString("shortMsg", shortMsg);
7080 info.putString("longMsg", longMsg);
7081 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7082 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007083 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007084 }
7085
Dan Egnor60d87622009-12-16 16:32:58 -08007086 // If we can't identify the process or it's already exceeded its crash quota,
7087 // quit right away without showing a crash dialog.
7088 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007089 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007090 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007091 }
7092
7093 Message msg = Message.obtain();
7094 msg.what = SHOW_ERROR_MSG;
7095 HashMap data = new HashMap();
7096 data.put("result", result);
7097 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007098 msg.obj = data;
7099 mHandler.sendMessage(msg);
7100
7101 Binder.restoreCallingIdentity(origId);
7102 }
7103
7104 int res = result.get();
7105
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007106 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007107 synchronized (this) {
7108 if (r != null) {
7109 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7110 SystemClock.uptimeMillis());
7111 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007112 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007113 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007114 }
7115 }
7116
7117 if (appErrorIntent != null) {
7118 try {
7119 mContext.startActivity(appErrorIntent);
7120 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007121 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007124 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007125
7126 Intent createAppErrorIntentLocked(ProcessRecord r,
7127 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7128 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007129 if (report == null) {
7130 return null;
7131 }
7132 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7133 result.setComponent(r.errorReportReceiver);
7134 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7135 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7136 return result;
7137 }
7138
Dan Egnorb7f03672009-12-09 16:22:32 -08007139 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7140 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007141 if (r.errorReportReceiver == null) {
7142 return null;
7143 }
7144
7145 if (!r.crashing && !r.notResponding) {
7146 return null;
7147 }
7148
Dan Egnorb7f03672009-12-09 16:22:32 -08007149 ApplicationErrorReport report = new ApplicationErrorReport();
7150 report.packageName = r.info.packageName;
7151 report.installerPackageName = r.errorReportReceiver.getPackageName();
7152 report.processName = r.processName;
7153 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007154 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007155
Dan Egnorb7f03672009-12-09 16:22:32 -08007156 if (r.crashing) {
7157 report.type = ApplicationErrorReport.TYPE_CRASH;
7158 report.crashInfo = crashInfo;
7159 } else if (r.notResponding) {
7160 report.type = ApplicationErrorReport.TYPE_ANR;
7161 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007162
Dan Egnorb7f03672009-12-09 16:22:32 -08007163 report.anrInfo.activity = r.notRespondingReport.tag;
7164 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7165 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007166 }
7167
Dan Egnorb7f03672009-12-09 16:22:32 -08007168 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007169 }
7170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007171 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7172 // assume our apps are happy - lazy create the list
7173 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7174
7175 synchronized (this) {
7176
7177 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007178 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7179 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007180 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7181 // This one's in trouble, so we'll generate a report for it
7182 // crashes are higher priority (in case there's a crash *and* an anr)
7183 ActivityManager.ProcessErrorStateInfo report = null;
7184 if (app.crashing) {
7185 report = app.crashingReport;
7186 } else if (app.notResponding) {
7187 report = app.notRespondingReport;
7188 }
7189
7190 if (report != null) {
7191 if (errList == null) {
7192 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7193 }
7194 errList.add(report);
7195 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007196 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007197 " crashing = " + app.crashing +
7198 " notResponding = " + app.notResponding);
7199 }
7200 }
7201 }
7202 }
7203
7204 return errList;
7205 }
7206
7207 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7208 // Lazy instantiation of list
7209 List<ActivityManager.RunningAppProcessInfo> runList = null;
7210 synchronized (this) {
7211 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007212 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7213 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007214 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7215 // Generate process state info for running application
7216 ActivityManager.RunningAppProcessInfo currApp =
7217 new ActivityManager.RunningAppProcessInfo(app.processName,
7218 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007219 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007220 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007221 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007222 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007223 if (app.persistent) {
7224 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007226 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007227 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7229 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7230 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007231 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7232 } else if (adj >= HOME_APP_ADJ) {
7233 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7234 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007235 } else if (adj >= SECONDARY_SERVER_ADJ) {
7236 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007237 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007238 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007239 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7240 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007241 } else if (adj >= VISIBLE_APP_ADJ) {
7242 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7243 } else {
7244 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7245 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007246 currApp.importanceReasonCode = app.adjTypeCode;
7247 if (app.adjSource instanceof ProcessRecord) {
7248 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007249 } else if (app.adjSource instanceof ActivityRecord) {
7250 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007251 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7252 }
7253 if (app.adjTarget instanceof ComponentName) {
7254 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7255 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007256 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007257 // + " lru=" + currApp.lru);
7258 if (runList == null) {
7259 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7260 }
7261 runList.add(currApp);
7262 }
7263 }
7264 }
7265 return runList;
7266 }
7267
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007268 public List<ApplicationInfo> getRunningExternalApplications() {
7269 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7270 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7271 if (runningApps != null && runningApps.size() > 0) {
7272 Set<String> extList = new HashSet<String>();
7273 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7274 if (app.pkgList != null) {
7275 for (String pkg : app.pkgList) {
7276 extList.add(pkg);
7277 }
7278 }
7279 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007280 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007281 for (String pkg : extList) {
7282 try {
7283 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7284 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7285 retList.add(info);
7286 }
7287 } catch (RemoteException e) {
7288 }
7289 }
7290 }
7291 return retList;
7292 }
7293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007294 @Override
7295 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007296 if (checkCallingPermission(android.Manifest.permission.DUMP)
7297 != PackageManager.PERMISSION_GRANTED) {
7298 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7299 + Binder.getCallingPid()
7300 + ", uid=" + Binder.getCallingUid()
7301 + " without permission "
7302 + android.Manifest.permission.DUMP);
7303 return;
7304 }
7305
7306 boolean dumpAll = false;
7307
7308 int opti = 0;
7309 while (opti < args.length) {
7310 String opt = args[opti];
7311 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7312 break;
7313 }
7314 opti++;
7315 if ("-a".equals(opt)) {
7316 dumpAll = true;
7317 } else if ("-h".equals(opt)) {
7318 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007319 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007320 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007321 pw.println(" a[ctivities]: activity stack state");
7322 pw.println(" b[roadcasts]: broadcast state");
7323 pw.println(" i[ntents]: pending intent state");
7324 pw.println(" p[rocesses]: process state");
7325 pw.println(" o[om]: out of memory management");
7326 pw.println(" prov[iders]: content provider state");
7327 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007328 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007330 } else {
7331 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007332 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007333 }
7334
7335 // Is the caller requesting to dump a particular piece of data?
7336 if (opti < args.length) {
7337 String cmd = args[opti];
7338 opti++;
7339 if ("activities".equals(cmd) || "a".equals(cmd)) {
7340 synchronized (this) {
7341 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007342 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007343 return;
7344 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7345 synchronized (this) {
7346 dumpBroadcastsLocked(fd, pw, args, opti, true);
7347 }
7348 return;
7349 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7350 synchronized (this) {
7351 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7352 }
7353 return;
7354 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7355 synchronized (this) {
7356 dumpProcessesLocked(fd, pw, args, opti, true);
7357 }
7358 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007359 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7360 synchronized (this) {
7361 dumpOomLocked(fd, pw, args, opti, true);
7362 }
7363 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007364 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7365 synchronized (this) {
7366 dumpProvidersLocked(fd, pw, args, opti, true);
7367 }
7368 return;
7369 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007370 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007371 return;
7372 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7373 synchronized (this) {
7374 dumpServicesLocked(fd, pw, args, opti, true);
7375 }
7376 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007377 } else {
7378 // Dumping a single activity?
7379 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7380 return;
7381 }
7382 pw.println("Bad activity command: " + cmd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007383 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007384 }
7385
7386 // No piece of data specified, dump everything.
7387 synchronized (this) {
7388 boolean needSep;
7389 if (dumpAll) {
7390 pw.println("Providers in Current Activity Manager State:");
7391 }
7392 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7393 if (needSep) {
7394 pw.println(" ");
7395 }
7396 if (dumpAll) {
7397 pw.println("-------------------------------------------------------------------------------");
7398 pw.println("Broadcasts in Current Activity Manager State:");
7399 }
7400 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7401 if (needSep) {
7402 pw.println(" ");
7403 }
7404 if (dumpAll) {
7405 pw.println("-------------------------------------------------------------------------------");
7406 pw.println("Services in Current Activity Manager State:");
7407 }
7408 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7409 if (needSep) {
7410 pw.println(" ");
7411 }
7412 if (dumpAll) {
7413 pw.println("-------------------------------------------------------------------------------");
7414 pw.println("PendingIntents in Current Activity Manager State:");
7415 }
7416 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7417 if (needSep) {
7418 pw.println(" ");
7419 }
7420 if (dumpAll) {
7421 pw.println("-------------------------------------------------------------------------------");
7422 pw.println("Activities in Current Activity Manager State:");
7423 }
7424 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7425 if (needSep) {
7426 pw.println(" ");
7427 }
7428 if (dumpAll) {
7429 pw.println("-------------------------------------------------------------------------------");
7430 pw.println("Processes in Current Activity Manager State:");
7431 }
7432 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7433 }
7434 }
7435
7436 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7437 int opti, boolean dumpAll, boolean needHeader) {
7438 if (needHeader) {
7439 pw.println(" Activity stack:");
7440 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007441 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007442 pw.println(" ");
7443 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007444 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7445 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007447 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007448 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007449 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007450 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007451 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007452 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007453 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007454 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007455 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007456 pw.println(" ");
7457 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007458 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007460
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007461 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007462 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7463 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007464 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007465 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007466
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007467 if (dumpAll && mRecentTasks.size() > 0) {
7468 pw.println(" ");
7469 pw.println("Recent tasks in Current Activity Manager State:");
7470
7471 final int N = mRecentTasks.size();
7472 for (int i=0; i<N; i++) {
7473 TaskRecord tr = mRecentTasks.get(i);
7474 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7475 pw.println(tr);
7476 mRecentTasks.get(i).dump(pw, " ");
7477 }
7478 }
7479
7480 pw.println(" ");
7481 pw.println(" mCurTask: " + mCurTask);
7482
7483 return true;
7484 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007485
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007486 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7487 int opti, boolean dumpAll) {
7488 boolean needSep = false;
7489 int numPers = 0;
7490
7491 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007492 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7493 final int NA = procs.size();
7494 for (int ia=0; ia<NA; ia++) {
7495 if (!needSep) {
7496 pw.println(" All known processes:");
7497 needSep = true;
7498 }
7499 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007500 pw.print(r.persistent ? " *PERS*" : " *APP*");
7501 pw.print(" UID "); pw.print(procs.keyAt(ia));
7502 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007503 r.dump(pw, " ");
7504 if (r.persistent) {
7505 numPers++;
7506 }
7507 }
7508 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007509 }
7510
7511 if (mLruProcesses.size() > 0) {
7512 if (needSep) pw.println(" ");
7513 needSep = true;
7514 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007515 dumpProcessOomList(pw, this, mLruProcesses, " ",
7516 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007517 needSep = true;
7518 }
7519
7520 synchronized (mPidsSelfLocked) {
7521 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007522 if (needSep) pw.println(" ");
7523 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007524 pw.println(" PID mappings:");
7525 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7526 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7527 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007528 }
7529 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007530 }
7531
7532 if (mForegroundProcesses.size() > 0) {
7533 if (needSep) pw.println(" ");
7534 needSep = true;
7535 pw.println(" Foreground Processes:");
7536 for (int i=0; i<mForegroundProcesses.size(); i++) {
7537 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7538 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007539 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007540 }
7541
7542 if (mPersistentStartingProcesses.size() > 0) {
7543 if (needSep) pw.println(" ");
7544 needSep = true;
7545 pw.println(" Persisent processes that are starting:");
7546 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007547 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007550 if (mStartingProcesses.size() > 0) {
7551 if (needSep) pw.println(" ");
7552 needSep = true;
7553 pw.println(" Processes that are starting:");
7554 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007555 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007557
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007558 if (mRemovedProcesses.size() > 0) {
7559 if (needSep) pw.println(" ");
7560 needSep = true;
7561 pw.println(" Processes that are being removed:");
7562 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007563 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007564 }
7565
7566 if (mProcessesOnHold.size() > 0) {
7567 if (needSep) pw.println(" ");
7568 needSep = true;
7569 pw.println(" Processes that are on old until the system is ready:");
7570 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007571 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007573
Dianne Hackborn287952c2010-09-22 22:34:31 -07007574 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007575
7576 if (mProcessCrashTimes.getMap().size() > 0) {
7577 if (needSep) pw.println(" ");
7578 needSep = true;
7579 pw.println(" Time since processes crashed:");
7580 long now = SystemClock.uptimeMillis();
7581 for (Map.Entry<String, SparseArray<Long>> procs
7582 : mProcessCrashTimes.getMap().entrySet()) {
7583 SparseArray<Long> uids = procs.getValue();
7584 final int N = uids.size();
7585 for (int i=0; i<N; i++) {
7586 pw.print(" Process "); pw.print(procs.getKey());
7587 pw.print(" uid "); pw.print(uids.keyAt(i));
7588 pw.print(": last crashed ");
7589 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007590 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007591 }
7592 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007594
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007595 if (mBadProcesses.getMap().size() > 0) {
7596 if (needSep) pw.println(" ");
7597 needSep = true;
7598 pw.println(" Bad processes:");
7599 for (Map.Entry<String, SparseArray<Long>> procs
7600 : mBadProcesses.getMap().entrySet()) {
7601 SparseArray<Long> uids = procs.getValue();
7602 final int N = uids.size();
7603 for (int i=0; i<N; i++) {
7604 pw.print(" Bad process "); pw.print(procs.getKey());
7605 pw.print(" uid "); pw.print(uids.keyAt(i));
7606 pw.print(": crashed at time ");
7607 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007608 }
7609 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007611
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007612 pw.println(" ");
7613 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007614 if (mHeavyWeightProcess != null) {
7615 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7616 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007617 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007618 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007619 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7620 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7621 || mOrigWaitForDebugger) {
7622 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7623 + " mDebugTransient=" + mDebugTransient
7624 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7625 }
7626 if (mAlwaysFinishActivities || mController != null) {
7627 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7628 + " mController=" + mController);
7629 }
7630 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007631 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007632 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007633 + " mProcessesReady=" + mProcessesReady
7634 + " mSystemReady=" + mSystemReady);
7635 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007636 + " mBooted=" + mBooted
7637 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007638 pw.print(" mLastPowerCheckRealtime=");
7639 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7640 pw.println("");
7641 pw.print(" mLastPowerCheckUptime=");
7642 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7643 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007644 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7645 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007646 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007647 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007648
7649 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650 }
7651
Dianne Hackborn287952c2010-09-22 22:34:31 -07007652 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7653 int opti, boolean needSep, boolean dumpAll) {
7654 if (mProcessesToGc.size() > 0) {
7655 if (needSep) pw.println(" ");
7656 needSep = true;
7657 pw.println(" Processes that are waiting to GC:");
7658 long now = SystemClock.uptimeMillis();
7659 for (int i=0; i<mProcessesToGc.size(); i++) {
7660 ProcessRecord proc = mProcessesToGc.get(i);
7661 pw.print(" Process "); pw.println(proc);
7662 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7663 pw.print(", last gced=");
7664 pw.print(now-proc.lastRequestedGc);
7665 pw.print(" ms ago, last lowMem=");
7666 pw.print(now-proc.lastLowMemory);
7667 pw.println(" ms ago");
7668
7669 }
7670 }
7671 return needSep;
7672 }
7673
7674 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7675 int opti, boolean dumpAll) {
7676 boolean needSep = false;
7677
7678 if (mLruProcesses.size() > 0) {
7679 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7680
7681 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7682 @Override
7683 public int compare(ProcessRecord object1, ProcessRecord object2) {
7684 if (object1.setAdj != object2.setAdj) {
7685 return object1.setAdj > object2.setAdj ? -1 : 1;
7686 }
7687 if (object1.setSchedGroup != object2.setSchedGroup) {
7688 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7689 }
7690 if (object1.keeping != object2.keeping) {
7691 return object1.keeping ? -1 : 1;
7692 }
7693 if (object1.pid != object2.pid) {
7694 return object1.pid > object2.pid ? -1 : 1;
7695 }
7696 return 0;
7697 }
7698 };
7699
7700 Collections.sort(procs, comparator);
7701
7702 if (needSep) pw.println(" ");
7703 needSep = true;
7704 pw.println(" Process OOM control:");
7705 dumpProcessOomList(pw, this, procs, " ",
7706 "Proc", "PERS", true);
7707 needSep = true;
7708 }
7709
7710 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7711
7712 pw.println(" ");
7713 pw.println(" mHomeProcess: " + mHomeProcess);
7714 if (mHeavyWeightProcess != null) {
7715 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7716 }
7717
7718 return true;
7719 }
7720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007721 /**
7722 * There are three ways to call this:
7723 * - no service specified: dump all the services
7724 * - a flattened component name that matched an existing service was specified as the
7725 * first arg: dump that one service
7726 * - the first arg isn't the flattened component name of an existing service:
7727 * dump all services whose component contains the first arg as a substring
7728 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007729 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 String[] newArgs;
7731 String componentNameString;
7732 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007733 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007734 componentNameString = null;
7735 newArgs = EMPTY_STRING_ARRAY;
7736 r = null;
7737 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007738 componentNameString = args[opti];
7739 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007740 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007741 synchronized (this) {
7742 r = componentName != null ? mServices.get(componentName) : null;
7743 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007744 newArgs = new String[args.length - opti];
7745 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007746 }
7747
7748 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007749 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007750 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007751 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7752 synchronized (this) {
7753 for (ServiceRecord r1 : mServices.values()) {
7754 if (componentNameString == null
7755 || r1.name.flattenToString().contains(componentNameString)) {
7756 services.add(r1);
7757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007758 }
7759 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007760 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007761 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007763 }
7764 }
7765
7766 /**
7767 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7768 * there is a thread associated with the service.
7769 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007770 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7771 pw.println("------------------------------------------------------------"
7772 + "-------------------");
7773 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774 if (r.app != null && r.app.thread != null) {
7775 try {
7776 // flush anything that is already in the PrintWriter since the thread is going
7777 // to write to the file descriptor directly
7778 pw.flush();
7779 r.app.thread.dumpService(fd, r, args);
7780 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007781 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 } catch (RemoteException e) {
7783 pw.println("got a RemoteException while dumping the service");
7784 }
7785 }
7786 }
7787
Dianne Hackborn625ac272010-09-17 18:29:22 -07007788 /**
7789 * There are three things that cmd can be:
7790 * - a flattened component name that matched an existing activity
7791 * - the cmd arg isn't the flattened component name of an existing activity:
7792 * dump all activity whose component contains the cmd as a substring
7793 * - A hex number of the ActivityRecord object instance.
7794 */
7795 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7796 int opti, boolean dumpAll) {
7797 String[] newArgs;
7798 ComponentName componentName = ComponentName.unflattenFromString(name);
7799 int objectId = 0;
7800 try {
7801 objectId = Integer.parseInt(name, 16);
7802 name = null;
7803 componentName = null;
7804 } catch (RuntimeException e) {
7805 }
7806 newArgs = new String[args.length - opti];
7807 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7808
7809 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7810 synchronized (this) {
7811 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7812 if (componentName != null) {
7813 if (r1.intent.getComponent().equals(componentName)) {
7814 activities.add(r1);
7815 }
7816 } else if (name != null) {
7817 if (r1.intent.getComponent().flattenToString().contains(name)) {
7818 activities.add(r1);
7819 }
7820 } else if (System.identityHashCode(this) == objectId) {
7821 activities.add(r1);
7822 }
7823 }
7824 }
7825
7826 if (activities.size() <= 0) {
7827 return false;
7828 }
7829
7830 for (int i=0; i<activities.size(); i++) {
7831 dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
7832 }
7833 return true;
7834 }
7835
7836 /**
7837 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7838 * there is a thread associated with the activity.
7839 */
7840 private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
7841 boolean dumpAll) {
7842 pw.println(" Activity " + r.intent.getComponent().flattenToString());
7843 if (dumpAll) {
7844 synchronized (this) {
7845 pw.print(" * "); pw.println(r);
7846 r.dump(pw, " ");
7847 }
7848 pw.println("");
7849 }
7850 if (r.app != null && r.app.thread != null) {
7851 try {
7852 // flush anything that is already in the PrintWriter since the thread is going
7853 // to write to the file descriptor directly
7854 pw.flush();
7855 r.app.thread.dumpActivity(fd, r, args);
7856 pw.print("\n");
7857 pw.flush();
7858 } catch (RemoteException e) {
7859 pw.println("got a RemoteException while dumping the activity");
7860 }
7861 }
7862 }
7863
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007864 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7865 int opti, boolean dumpAll) {
7866 boolean needSep = false;
7867
7868 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007869 if (mRegisteredReceivers.size() > 0) {
7870 pw.println(" ");
7871 pw.println(" Registered Receivers:");
7872 Iterator it = mRegisteredReceivers.values().iterator();
7873 while (it.hasNext()) {
7874 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007875 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007876 r.dump(pw, " ");
7877 }
7878 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 pw.println(" ");
7881 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007882 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007883 needSep = true;
7884 }
7885
7886 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7887 || mPendingBroadcast != null) {
7888 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007889 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007890 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007891 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007892 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7893 pw.println(" Broadcast #" + i + ":");
7894 mParallelBroadcasts.get(i).dump(pw, " ");
7895 }
7896 if (mOrderedBroadcasts.size() > 0) {
7897 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007898 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007899 }
7900 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7901 pw.println(" Serialized Broadcast #" + i + ":");
7902 mOrderedBroadcasts.get(i).dump(pw, " ");
7903 }
7904 pw.println(" ");
7905 pw.println(" Pending broadcast:");
7906 if (mPendingBroadcast != null) {
7907 mPendingBroadcast.dump(pw, " ");
7908 } else {
7909 pw.println(" (null)");
7910 }
7911 needSep = true;
7912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007913
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007914 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007916 pw.println(" Historical broadcasts:");
7917 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7918 BroadcastRecord r = mBroadcastHistory[i];
7919 if (r == null) {
7920 break;
7921 }
7922 pw.println(" Historical Broadcast #" + i + ":");
7923 r.dump(pw, " ");
7924 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007925 needSep = true;
7926 }
7927
7928 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007929 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007930 pw.println(" Sticky broadcasts:");
7931 StringBuilder sb = new StringBuilder(128);
7932 for (Map.Entry<String, ArrayList<Intent>> ent
7933 : mStickyBroadcasts.entrySet()) {
7934 pw.print(" * Sticky action "); pw.print(ent.getKey());
7935 pw.println(":");
7936 ArrayList<Intent> intents = ent.getValue();
7937 final int N = intents.size();
7938 for (int i=0; i<N; i++) {
7939 sb.setLength(0);
7940 sb.append(" Intent: ");
7941 intents.get(i).toShortString(sb, true, false);
7942 pw.println(sb.toString());
7943 Bundle bundle = intents.get(i).getExtras();
7944 if (bundle != null) {
7945 pw.print(" ");
7946 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007947 }
7948 }
7949 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007950 needSep = true;
7951 }
7952
7953 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007954 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007955 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007956 pw.println(" mHandler:");
7957 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007958 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007959 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007960
7961 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007962 }
7963
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007964 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7965 int opti, boolean dumpAll) {
7966 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007968 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007969 if (mServices.size() > 0) {
7970 pw.println(" Active services:");
7971 Iterator<ServiceRecord> it = mServices.values().iterator();
7972 while (it.hasNext()) {
7973 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007974 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007975 r.dump(pw, " ");
7976 }
7977 needSep = true;
7978 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007981 if (mPendingServices.size() > 0) {
7982 if (needSep) pw.println(" ");
7983 pw.println(" Pending services:");
7984 for (int i=0; i<mPendingServices.size(); i++) {
7985 ServiceRecord r = mPendingServices.get(i);
7986 pw.print(" * Pending "); pw.println(r);
7987 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007988 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007989 needSep = true;
7990 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007991
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007992 if (mRestartingServices.size() > 0) {
7993 if (needSep) pw.println(" ");
7994 pw.println(" Restarting services:");
7995 for (int i=0; i<mRestartingServices.size(); i++) {
7996 ServiceRecord r = mRestartingServices.get(i);
7997 pw.print(" * Restarting "); pw.println(r);
7998 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007999 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008000 needSep = true;
8001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008002
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008003 if (mStoppingServices.size() > 0) {
8004 if (needSep) pw.println(" ");
8005 pw.println(" Stopping services:");
8006 for (int i=0; i<mStoppingServices.size(); i++) {
8007 ServiceRecord r = mStoppingServices.get(i);
8008 pw.print(" * Stopping "); pw.println(r);
8009 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008010 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008011 needSep = true;
8012 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008013
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008014 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008015 if (mServiceConnections.size() > 0) {
8016 if (needSep) pw.println(" ");
8017 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008018 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008019 = mServiceConnections.values().iterator();
8020 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008021 ArrayList<ConnectionRecord> r = it.next();
8022 for (int i=0; i<r.size(); i++) {
8023 pw.print(" * "); pw.println(r.get(i));
8024 r.get(i).dump(pw, " ");
8025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008026 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008027 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008028 }
8029 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008030
8031 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 }
8033
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008034 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8035 int opti, boolean dumpAll) {
8036 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008038 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008039 if (mProvidersByClass.size() > 0) {
8040 if (needSep) pw.println(" ");
8041 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008042 Iterator<Map.Entry<String, ContentProviderRecord>> it
8043 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008044 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008045 Map.Entry<String, ContentProviderRecord> e = it.next();
8046 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008047 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 r.dump(pw, " ");
8049 }
8050 needSep = true;
8051 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008052
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008053 if (mProvidersByName.size() > 0) {
8054 pw.println(" ");
8055 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008056 Iterator<Map.Entry<String, ContentProviderRecord>> it
8057 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008058 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008059 Map.Entry<String, ContentProviderRecord> e = it.next();
8060 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008061 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8062 pw.println(r);
8063 }
8064 needSep = true;
8065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008067
8068 if (mLaunchingProviders.size() > 0) {
8069 if (needSep) pw.println(" ");
8070 pw.println(" Launching content providers:");
8071 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8072 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8073 pw.println(mLaunchingProviders.get(i));
8074 }
8075 needSep = true;
8076 }
8077
8078 if (mGrantedUriPermissions.size() > 0) {
8079 pw.println();
8080 pw.println("Granted Uri Permissions:");
8081 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8082 int uid = mGrantedUriPermissions.keyAt(i);
8083 HashMap<Uri, UriPermission> perms
8084 = mGrantedUriPermissions.valueAt(i);
8085 pw.print(" * UID "); pw.print(uid);
8086 pw.println(" holds:");
8087 for (UriPermission perm : perms.values()) {
8088 pw.print(" "); pw.println(perm);
8089 perm.dump(pw, " ");
8090 }
8091 }
8092 needSep = true;
8093 }
8094
8095 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008096 }
8097
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008098 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8099 int opti, boolean dumpAll) {
8100 boolean needSep = false;
8101
8102 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008103 if (this.mIntentSenderRecords.size() > 0) {
8104 Iterator<WeakReference<PendingIntentRecord>> it
8105 = mIntentSenderRecords.values().iterator();
8106 while (it.hasNext()) {
8107 WeakReference<PendingIntentRecord> ref = it.next();
8108 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008109 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008110 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008111 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008112 rec.dump(pw, " ");
8113 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008114 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008115 }
8116 }
8117 }
8118 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008119
8120 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008121 }
8122
8123 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008124 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008125 TaskRecord lastTask = null;
8126 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008127 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008128 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008129 if (lastTask != r.task) {
8130 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008131 pw.print(prefix);
8132 pw.print(full ? "* " : " ");
8133 pw.println(lastTask);
8134 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008135 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008138 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8139 pw.print(" #"); pw.print(i); pw.print(": ");
8140 pw.println(r);
8141 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008142 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008144 }
8145 }
8146
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008147 private static String buildOomTag(String prefix, String space, int val, int base) {
8148 if (val == base) {
8149 if (space == null) return prefix;
8150 return prefix + " ";
8151 }
8152 return prefix + "+" + Integer.toString(val-base);
8153 }
8154
8155 private static final int dumpProcessList(PrintWriter pw,
8156 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008157 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008158 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008159 final int N = list.size()-1;
8160 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008161 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008162 pw.println(String.format("%s%s #%2d: %s",
8163 prefix, (r.persistent ? persistentLabel : normalLabel),
8164 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165 if (r.persistent) {
8166 numPers++;
8167 }
8168 }
8169 return numPers;
8170 }
8171
Dianne Hackborn287952c2010-09-22 22:34:31 -07008172 private static final void dumpProcessOomList(PrintWriter pw,
8173 ActivityManagerService service, List<ProcessRecord> list,
8174 String prefix, String normalLabel, String persistentLabel,
8175 boolean inclDetails) {
8176
8177 final long curRealtime = SystemClock.elapsedRealtime();
8178 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8179 final long curUptime = SystemClock.uptimeMillis();
8180 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8181
8182 final int N = list.size()-1;
8183 for (int i=N; i>=0; i--) {
8184 ProcessRecord r = list.get(i);
8185 String oomAdj;
8186 if (r.setAdj >= EMPTY_APP_ADJ) {
8187 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8188 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8189 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8190 } else if (r.setAdj >= HOME_APP_ADJ) {
8191 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8192 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8193 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8194 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8195 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8196 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8197 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8198 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8199 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8200 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8201 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8202 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8203 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8204 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8205 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8206 } else if (r.setAdj >= SYSTEM_ADJ) {
8207 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8208 } else {
8209 oomAdj = Integer.toString(r.setAdj);
8210 }
8211 String schedGroup;
8212 switch (r.setSchedGroup) {
8213 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8214 schedGroup = "B";
8215 break;
8216 case Process.THREAD_GROUP_DEFAULT:
8217 schedGroup = "F";
8218 break;
8219 default:
8220 schedGroup = Integer.toString(r.setSchedGroup);
8221 break;
8222 }
8223 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8224 prefix, (r.persistent ? persistentLabel : normalLabel),
8225 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8226 if (r.adjSource != null || r.adjTarget != null) {
8227 pw.print(prefix);
8228 pw.print(" ");
8229 if (r.adjTarget instanceof ComponentName) {
8230 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8231 } else if (r.adjTarget != null) {
8232 pw.print(r.adjTarget.toString());
8233 } else {
8234 pw.print("{null}");
8235 }
8236 pw.print("<=");
8237 if (r.adjSource instanceof ProcessRecord) {
8238 pw.print("Proc{");
8239 pw.print(((ProcessRecord)r.adjSource).toShortString());
8240 pw.println("}");
8241 } else if (r.adjSource != null) {
8242 pw.println(r.adjSource.toString());
8243 } else {
8244 pw.println("{null}");
8245 }
8246 }
8247 if (inclDetails) {
8248 pw.print(prefix);
8249 pw.print(" ");
8250 pw.print("oom: max="); pw.print(r.maxAdj);
8251 pw.print(" hidden="); pw.print(r.hiddenAdj);
8252 pw.print(" curRaw="); pw.print(r.curRawAdj);
8253 pw.print(" setRaw="); pw.print(r.setRawAdj);
8254 pw.print(" cur="); pw.print(r.curAdj);
8255 pw.print(" set="); pw.println(r.setAdj);
8256 pw.print(prefix);
8257 pw.print(" ");
8258 pw.print("keeping="); pw.print(r.keeping);
8259 pw.print(" hidden="); pw.print(r.hidden);
8260 pw.print(" empty="); pw.println(r.empty);
8261
8262 if (!r.keeping) {
8263 if (r.lastWakeTime != 0) {
8264 long wtime;
8265 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8266 synchronized (stats) {
8267 wtime = stats.getProcessWakeTime(r.info.uid,
8268 r.pid, curRealtime);
8269 }
8270 long timeUsed = wtime - r.lastWakeTime;
8271 pw.print(prefix);
8272 pw.print(" ");
8273 pw.print("keep awake over ");
8274 TimeUtils.formatDuration(realtimeSince, pw);
8275 pw.print(" used ");
8276 TimeUtils.formatDuration(timeUsed, pw);
8277 pw.print(" (");
8278 pw.print((timeUsed*100)/realtimeSince);
8279 pw.println("%)");
8280 }
8281 if (r.lastCpuTime != 0) {
8282 long timeUsed = r.curCpuTime - r.lastCpuTime;
8283 pw.print(prefix);
8284 pw.print(" ");
8285 pw.print("run cpu over ");
8286 TimeUtils.formatDuration(uptimeSince, pw);
8287 pw.print(" used ");
8288 TimeUtils.formatDuration(timeUsed, pw);
8289 pw.print(" (");
8290 pw.print((timeUsed*100)/uptimeSince);
8291 pw.println("%)");
8292 }
8293 }
8294 }
8295 }
8296 }
8297
Dianne Hackborn472ad872010-04-07 17:31:48 -07008298 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008299 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008300 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008301 long uptime = SystemClock.uptimeMillis();
8302 long realtime = SystemClock.elapsedRealtime();
8303
8304 if (isCheckinRequest) {
8305 // short checkin version
8306 pw.println(uptime + "," + realtime);
8307 pw.flush();
8308 } else {
8309 pw.println("Applications Memory Usage (kB):");
8310 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8311 }
8312 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8313 ProcessRecord r = (ProcessRecord)list.get(i);
8314 if (r.thread != null) {
8315 if (!isCheckinRequest) {
8316 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8317 pw.flush();
8318 }
8319 try {
8320 r.thread.asBinder().dump(fd, args);
8321 } catch (RemoteException e) {
8322 if (!isCheckinRequest) {
8323 pw.println("Got RemoteException!");
8324 pw.flush();
8325 }
8326 }
8327 }
8328 }
8329 }
8330
8331 /**
8332 * Searches array of arguments for the specified string
8333 * @param args array of argument strings
8334 * @param value value to search for
8335 * @return true if the value is contained in the array
8336 */
8337 private static boolean scanArgs(String[] args, String value) {
8338 if (args != null) {
8339 for (String arg : args) {
8340 if (value.equals(arg)) {
8341 return true;
8342 }
8343 }
8344 }
8345 return false;
8346 }
8347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008348 private final void killServicesLocked(ProcessRecord app,
8349 boolean allowRestart) {
8350 // Report disconnected services.
8351 if (false) {
8352 // XXX we are letting the client link to the service for
8353 // death notifications.
8354 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008355 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008356 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008357 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008358 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008359 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008360 = r.connections.values().iterator();
8361 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008362 ArrayList<ConnectionRecord> cl = jt.next();
8363 for (int i=0; i<cl.size(); i++) {
8364 ConnectionRecord c = cl.get(i);
8365 if (c.binding.client != app) {
8366 try {
8367 //c.conn.connected(r.className, null);
8368 } catch (Exception e) {
8369 // todo: this should be asynchronous!
8370 Slog.w(TAG, "Exception thrown disconnected servce "
8371 + r.shortName
8372 + " from app " + app.processName, e);
8373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008374 }
8375 }
8376 }
8377 }
8378 }
8379 }
8380 }
8381
8382 // Clean up any connections this application has to other services.
8383 if (app.connections.size() > 0) {
8384 Iterator<ConnectionRecord> it = app.connections.iterator();
8385 while (it.hasNext()) {
8386 ConnectionRecord r = it.next();
8387 removeConnectionLocked(r, app, null);
8388 }
8389 }
8390 app.connections.clear();
8391
8392 if (app.services.size() != 0) {
8393 // Any services running in the application need to be placed
8394 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008395 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008396 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008397 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008398 synchronized (sr.stats.getBatteryStats()) {
8399 sr.stats.stopLaunchedLocked();
8400 }
8401 sr.app = null;
8402 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008403 if (mStoppingServices.remove(sr)) {
8404 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8405 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008406
8407 boolean hasClients = sr.bindings.size() > 0;
8408 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008409 Iterator<IntentBindRecord> bindings
8410 = sr.bindings.values().iterator();
8411 while (bindings.hasNext()) {
8412 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008413 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008414 + ": shouldUnbind=" + b.hasBound);
8415 b.binder = null;
8416 b.requested = b.received = b.hasBound = false;
8417 }
8418 }
8419
8420 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008421 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008422 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008423 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008424 sr.crashCount, sr.shortName, app.pid);
8425 bringDownServiceLocked(sr, true);
8426 } else if (!allowRestart) {
8427 bringDownServiceLocked(sr, true);
8428 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008429 boolean canceled = scheduleServiceRestartLocked(sr, true);
8430
8431 // Should the service remain running? Note that in the
8432 // extreme case of so many attempts to deliver a command
8433 // that it failed, that we also will stop it here.
8434 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8435 if (sr.pendingStarts.size() == 0) {
8436 sr.startRequested = false;
8437 if (!hasClients) {
8438 // Whoops, no reason to restart!
8439 bringDownServiceLocked(sr, true);
8440 }
8441 }
8442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443 }
8444 }
8445
8446 if (!allowRestart) {
8447 app.services.clear();
8448 }
8449 }
8450
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008451 // Make sure we have no more records on the stopping list.
8452 int i = mStoppingServices.size();
8453 while (i > 0) {
8454 i--;
8455 ServiceRecord sr = mStoppingServices.get(i);
8456 if (sr.app == app) {
8457 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008458 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008459 }
8460 }
8461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008462 app.executingServices.clear();
8463 }
8464
8465 private final void removeDyingProviderLocked(ProcessRecord proc,
8466 ContentProviderRecord cpr) {
8467 synchronized (cpr) {
8468 cpr.launchingApp = null;
8469 cpr.notifyAll();
8470 }
8471
8472 mProvidersByClass.remove(cpr.info.name);
8473 String names[] = cpr.info.authority.split(";");
8474 for (int j = 0; j < names.length; j++) {
8475 mProvidersByName.remove(names[j]);
8476 }
8477
8478 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8479 while (cit.hasNext()) {
8480 ProcessRecord capp = cit.next();
8481 if (!capp.persistent && capp.thread != null
8482 && capp.pid != 0
8483 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008484 Slog.i(TAG, "Kill " + capp.processName
8485 + " (pid " + capp.pid + "): provider " + cpr.info.name
8486 + " in dying process " + proc.processName);
8487 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8488 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008489 Process.killProcess(capp.pid);
8490 }
8491 }
8492
8493 mLaunchingProviders.remove(cpr);
8494 }
8495
8496 /**
8497 * Main code for cleaning up a process when it has gone away. This is
8498 * called both as a result of the process dying, or directly when stopping
8499 * a process when running in single process mode.
8500 */
8501 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8502 boolean restarting, int index) {
8503 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008504 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008505 }
8506
Dianne Hackborn36124872009-10-08 16:22:03 -07008507 mProcessesToGc.remove(app);
8508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008509 // Dismiss any open dialogs.
8510 if (app.crashDialog != null) {
8511 app.crashDialog.dismiss();
8512 app.crashDialog = null;
8513 }
8514 if (app.anrDialog != null) {
8515 app.anrDialog.dismiss();
8516 app.anrDialog = null;
8517 }
8518 if (app.waitDialog != null) {
8519 app.waitDialog.dismiss();
8520 app.waitDialog = null;
8521 }
8522
8523 app.crashing = false;
8524 app.notResponding = false;
8525
8526 app.resetPackageList();
8527 app.thread = null;
8528 app.forcingToForeground = null;
8529 app.foregroundServices = false;
8530
8531 killServicesLocked(app, true);
8532
8533 boolean restart = false;
8534
8535 int NL = mLaunchingProviders.size();
8536
8537 // Remove published content providers.
8538 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008539 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008541 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008542 cpr.provider = null;
8543 cpr.app = null;
8544
8545 // See if someone is waiting for this provider... in which
8546 // case we don't remove it, but just let it restart.
8547 int i = 0;
8548 if (!app.bad) {
8549 for (; i<NL; i++) {
8550 if (mLaunchingProviders.get(i) == cpr) {
8551 restart = true;
8552 break;
8553 }
8554 }
8555 } else {
8556 i = NL;
8557 }
8558
8559 if (i >= NL) {
8560 removeDyingProviderLocked(app, cpr);
8561 NL = mLaunchingProviders.size();
8562 }
8563 }
8564 app.pubProviders.clear();
8565 }
8566
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008567 // Take care of any launching providers waiting for this process.
8568 if (checkAppInLaunchingProvidersLocked(app, false)) {
8569 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008570 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008572 // Unregister from connected content providers.
8573 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008574 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008575 while (it.hasNext()) {
8576 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8577 cpr.clients.remove(app);
8578 }
8579 app.conProviders.clear();
8580 }
8581
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008582 // At this point there may be remaining entries in mLaunchingProviders
8583 // where we were the only one waiting, so they are no longer of use.
8584 // Look for these and clean up if found.
8585 // XXX Commented out for now. Trying to figure out a way to reproduce
8586 // the actual situation to identify what is actually going on.
8587 if (false) {
8588 for (int i=0; i<NL; i++) {
8589 ContentProviderRecord cpr = (ContentProviderRecord)
8590 mLaunchingProviders.get(i);
8591 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8592 synchronized (cpr) {
8593 cpr.launchingApp = null;
8594 cpr.notifyAll();
8595 }
8596 }
8597 }
8598 }
8599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008600 skipCurrentReceiverLocked(app);
8601
8602 // Unregister any receivers.
8603 if (app.receivers.size() > 0) {
8604 Iterator<ReceiverList> it = app.receivers.iterator();
8605 while (it.hasNext()) {
8606 removeReceiverLocked(it.next());
8607 }
8608 app.receivers.clear();
8609 }
8610
Christopher Tate181fafa2009-05-14 11:12:14 -07008611 // If the app is undergoing backup, tell the backup manager about it
8612 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008613 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008614 try {
8615 IBackupManager bm = IBackupManager.Stub.asInterface(
8616 ServiceManager.getService(Context.BACKUP_SERVICE));
8617 bm.agentDisconnected(app.info.packageName);
8618 } catch (RemoteException e) {
8619 // can't happen; backup manager is local
8620 }
8621 }
8622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008623 // If the caller is restarting this app, then leave it in its
8624 // current lists and let the caller take care of it.
8625 if (restarting) {
8626 return;
8627 }
8628
8629 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008630 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008631 "Removing non-persistent process during cleanup: " + app);
8632 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008633 if (mHeavyWeightProcess == app) {
8634 mHeavyWeightProcess = null;
8635 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8636 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008637 } else if (!app.removed) {
8638 // This app is persistent, so we need to keep its record around.
8639 // If it is not already on the pending app list, add it there
8640 // and start a new process for it.
8641 app.thread = null;
8642 app.forcingToForeground = null;
8643 app.foregroundServices = false;
8644 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8645 mPersistentStartingProcesses.add(app);
8646 restart = true;
8647 }
8648 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008649 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8650 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008651 mProcessesOnHold.remove(app);
8652
The Android Open Source Project4df24232009-03-05 14:34:35 -08008653 if (app == mHomeProcess) {
8654 mHomeProcess = null;
8655 }
8656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008657 if (restart) {
8658 // We have components that still need to be running in the
8659 // process, so re-launch it.
8660 mProcessNames.put(app.processName, app.info.uid, app);
8661 startProcessLocked(app, "restart", app.processName);
8662 } else if (app.pid > 0 && app.pid != MY_PID) {
8663 // Goodbye!
8664 synchronized (mPidsSelfLocked) {
8665 mPidsSelfLocked.remove(app.pid);
8666 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8667 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008668 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 }
8670 }
8671
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008672 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8673 // Look through the content providers we are waiting to have launched,
8674 // and if any run in this process then either schedule a restart of
8675 // the process or kill the client waiting for it if this process has
8676 // gone bad.
8677 int NL = mLaunchingProviders.size();
8678 boolean restart = false;
8679 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008680 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008681 if (cpr.launchingApp == app) {
8682 if (!alwaysBad && !app.bad) {
8683 restart = true;
8684 } else {
8685 removeDyingProviderLocked(app, cpr);
8686 NL = mLaunchingProviders.size();
8687 }
8688 }
8689 }
8690 return restart;
8691 }
8692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008693 // =========================================================
8694 // SERVICES
8695 // =========================================================
8696
8697 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8698 ActivityManager.RunningServiceInfo info =
8699 new ActivityManager.RunningServiceInfo();
8700 info.service = r.name;
8701 if (r.app != null) {
8702 info.pid = r.app.pid;
8703 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008704 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008705 info.process = r.processName;
8706 info.foreground = r.isForeground;
8707 info.activeSince = r.createTime;
8708 info.started = r.startRequested;
8709 info.clientCount = r.connections.size();
8710 info.crashCount = r.crashCount;
8711 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008712 if (r.isForeground) {
8713 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8714 }
8715 if (r.startRequested) {
8716 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8717 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008718 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008719 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8720 }
8721 if (r.app != null && r.app.persistent) {
8722 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8723 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008724
8725 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8726 for (int i=0; i<connl.size(); i++) {
8727 ConnectionRecord conn = connl.get(i);
8728 if (conn.clientLabel != 0) {
8729 info.clientPackage = conn.binding.client.info.packageName;
8730 info.clientLabel = conn.clientLabel;
8731 return info;
8732 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008733 }
8734 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008735 return info;
8736 }
8737
8738 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8739 int flags) {
8740 synchronized (this) {
8741 ArrayList<ActivityManager.RunningServiceInfo> res
8742 = new ArrayList<ActivityManager.RunningServiceInfo>();
8743
8744 if (mServices.size() > 0) {
8745 Iterator<ServiceRecord> it = mServices.values().iterator();
8746 while (it.hasNext() && res.size() < maxNum) {
8747 res.add(makeRunningServiceInfoLocked(it.next()));
8748 }
8749 }
8750
8751 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8752 ServiceRecord r = mRestartingServices.get(i);
8753 ActivityManager.RunningServiceInfo info =
8754 makeRunningServiceInfoLocked(r);
8755 info.restarting = r.nextRestartTime;
8756 res.add(info);
8757 }
8758
8759 return res;
8760 }
8761 }
8762
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008763 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8764 synchronized (this) {
8765 ServiceRecord r = mServices.get(name);
8766 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008767 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8768 for (int i=0; i<conn.size(); i++) {
8769 if (conn.get(i).clientIntent != null) {
8770 return conn.get(i).clientIntent;
8771 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008772 }
8773 }
8774 }
8775 }
8776 return null;
8777 }
8778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008779 private final ServiceRecord findServiceLocked(ComponentName name,
8780 IBinder token) {
8781 ServiceRecord r = mServices.get(name);
8782 return r == token ? r : null;
8783 }
8784
8785 private final class ServiceLookupResult {
8786 final ServiceRecord record;
8787 final String permission;
8788
8789 ServiceLookupResult(ServiceRecord _record, String _permission) {
8790 record = _record;
8791 permission = _permission;
8792 }
8793 };
8794
8795 private ServiceLookupResult findServiceLocked(Intent service,
8796 String resolvedType) {
8797 ServiceRecord r = null;
8798 if (service.getComponent() != null) {
8799 r = mServices.get(service.getComponent());
8800 }
8801 if (r == null) {
8802 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8803 r = mServicesByIntent.get(filter);
8804 }
8805
8806 if (r == null) {
8807 try {
8808 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008809 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008810 service, resolvedType, 0);
8811 ServiceInfo sInfo =
8812 rInfo != null ? rInfo.serviceInfo : null;
8813 if (sInfo == null) {
8814 return null;
8815 }
8816
8817 ComponentName name = new ComponentName(
8818 sInfo.applicationInfo.packageName, sInfo.name);
8819 r = mServices.get(name);
8820 } catch (RemoteException ex) {
8821 // pm is in same process, this will never happen.
8822 }
8823 }
8824 if (r != null) {
8825 int callingPid = Binder.getCallingPid();
8826 int callingUid = Binder.getCallingUid();
8827 if (checkComponentPermission(r.permission,
8828 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8829 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008830 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008831 + " from pid=" + callingPid
8832 + ", uid=" + callingUid
8833 + " requires " + r.permission);
8834 return new ServiceLookupResult(null, r.permission);
8835 }
8836 return new ServiceLookupResult(r, null);
8837 }
8838 return null;
8839 }
8840
8841 private class ServiceRestarter implements Runnable {
8842 private ServiceRecord mService;
8843
8844 void setService(ServiceRecord service) {
8845 mService = service;
8846 }
8847
8848 public void run() {
8849 synchronized(ActivityManagerService.this) {
8850 performServiceRestartLocked(mService);
8851 }
8852 }
8853 }
8854
8855 private ServiceLookupResult retrieveServiceLocked(Intent service,
8856 String resolvedType, int callingPid, int callingUid) {
8857 ServiceRecord r = null;
8858 if (service.getComponent() != null) {
8859 r = mServices.get(service.getComponent());
8860 }
8861 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8862 r = mServicesByIntent.get(filter);
8863 if (r == null) {
8864 try {
8865 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008866 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008867 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008868 ServiceInfo sInfo =
8869 rInfo != null ? rInfo.serviceInfo : null;
8870 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008871 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008872 ": not found");
8873 return null;
8874 }
8875
8876 ComponentName name = new ComponentName(
8877 sInfo.applicationInfo.packageName, sInfo.name);
8878 r = mServices.get(name);
8879 if (r == null) {
8880 filter = new Intent.FilterComparison(service.cloneFilter());
8881 ServiceRestarter res = new ServiceRestarter();
8882 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8883 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8884 synchronized (stats) {
8885 ss = stats.getServiceStatsLocked(
8886 sInfo.applicationInfo.uid, sInfo.packageName,
8887 sInfo.name);
8888 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008889 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008890 res.setService(r);
8891 mServices.put(name, r);
8892 mServicesByIntent.put(filter, r);
8893
8894 // Make sure this component isn't in the pending list.
8895 int N = mPendingServices.size();
8896 for (int i=0; i<N; i++) {
8897 ServiceRecord pr = mPendingServices.get(i);
8898 if (pr.name.equals(name)) {
8899 mPendingServices.remove(i);
8900 i--;
8901 N--;
8902 }
8903 }
8904 }
8905 } catch (RemoteException ex) {
8906 // pm is in same process, this will never happen.
8907 }
8908 }
8909 if (r != null) {
8910 if (checkComponentPermission(r.permission,
8911 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8912 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008913 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008914 + " from pid=" + Binder.getCallingPid()
8915 + ", uid=" + Binder.getCallingUid()
8916 + " requires " + r.permission);
8917 return new ServiceLookupResult(null, r.permission);
8918 }
8919 return new ServiceLookupResult(r, null);
8920 }
8921 return null;
8922 }
8923
Dianne Hackborn287952c2010-09-22 22:34:31 -07008924 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8925 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8926 + why + " of " + r + " in app " + r.app);
8927 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8928 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008929 long now = SystemClock.uptimeMillis();
8930 if (r.executeNesting == 0 && r.app != null) {
8931 if (r.app.executingServices.size() == 0) {
8932 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8933 msg.obj = r.app;
8934 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8935 }
8936 r.app.executingServices.add(r);
8937 }
8938 r.executeNesting++;
8939 r.executingStart = now;
8940 }
8941
8942 private final void sendServiceArgsLocked(ServiceRecord r,
8943 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008944 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008945 if (N == 0) {
8946 return;
8947 }
8948
Dianne Hackborn39792d22010-08-19 18:01:52 -07008949 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008950 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008951 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008952 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8953 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008954 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008955 // If somehow we got a dummy start at the front, then
8956 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008957 continue;
8958 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008959 si.deliveredTime = SystemClock.uptimeMillis();
8960 r.deliveredStarts.add(si);
8961 si.deliveryCount++;
8962 if (si.targetPermissionUid >= 0) {
8963 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008964 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008965 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008966 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008967 if (!oomAdjusted) {
8968 oomAdjusted = true;
8969 updateOomAdjLocked(r.app);
8970 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008971 int flags = 0;
8972 if (si.deliveryCount > 0) {
8973 flags |= Service.START_FLAG_RETRY;
8974 }
8975 if (si.doneExecutingCount > 0) {
8976 flags |= Service.START_FLAG_REDELIVERY;
8977 }
8978 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008979 } catch (RemoteException e) {
8980 // Remote process gone... we'll let the normal cleanup take
8981 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008982 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008983 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008985 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008986 break;
8987 }
8988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008989 }
8990
8991 private final boolean requestServiceBindingLocked(ServiceRecord r,
8992 IntentBindRecord i, boolean rebind) {
8993 if (r.app == null || r.app.thread == null) {
8994 // If service is not currently running, can't yet bind.
8995 return false;
8996 }
8997 if ((!i.requested || rebind) && i.apps.size() > 0) {
8998 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008999 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009000 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9001 if (!rebind) {
9002 i.requested = true;
9003 }
9004 i.hasBound = true;
9005 i.doRebind = false;
9006 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009007 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009008 return false;
9009 }
9010 }
9011 return true;
9012 }
9013
9014 private final void requestServiceBindingsLocked(ServiceRecord r) {
9015 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9016 while (bindings.hasNext()) {
9017 IntentBindRecord i = bindings.next();
9018 if (!requestServiceBindingLocked(r, i, false)) {
9019 break;
9020 }
9021 }
9022 }
9023
9024 private final void realStartServiceLocked(ServiceRecord r,
9025 ProcessRecord app) throws RemoteException {
9026 if (app.thread == null) {
9027 throw new RemoteException();
9028 }
9029
9030 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009031 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009032
9033 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009034 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009035 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009036
9037 boolean created = false;
9038 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009039 mStringBuilder.setLength(0);
9040 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009041 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009042 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009043 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009044 synchronized (r.stats.getBatteryStats()) {
9045 r.stats.startLaunchedLocked();
9046 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009047 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009048 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009049 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009050 created = true;
9051 } finally {
9052 if (!created) {
9053 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009054 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 }
9056 }
9057
9058 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009059
9060 // If the service is in the started state, and there are no
9061 // pending arguments, then fake up one so its onStartCommand() will
9062 // be called.
9063 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9064 r.lastStartId++;
9065 if (r.lastStartId < 1) {
9066 r.lastStartId = 1;
9067 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009068 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009069 }
9070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009071 sendServiceArgsLocked(r, true);
9072 }
9073
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009074 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9075 boolean allowCancel) {
9076 boolean canceled = false;
9077
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009078 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009079 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009080 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009081
9082 // Any delivered but not yet finished starts should be put back
9083 // on the pending list.
9084 final int N = r.deliveredStarts.size();
9085 if (N > 0) {
9086 for (int i=N-1; i>=0; i--) {
9087 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009088 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009089 if (si.intent == null) {
9090 // We'll generate this again if needed.
9091 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9092 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9093 r.pendingStarts.add(0, si);
9094 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9095 dur *= 2;
9096 if (minDuration < dur) minDuration = dur;
9097 if (resetTime < dur) resetTime = dur;
9098 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009099 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009100 + r.name);
9101 canceled = true;
9102 }
9103 }
9104 r.deliveredStarts.clear();
9105 }
9106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009107 r.totalRestartCount++;
9108 if (r.restartDelay == 0) {
9109 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009110 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009111 } else {
9112 // If it has been a "reasonably long time" since the service
9113 // was started, then reset our restart duration back to
9114 // the beginning, so we don't infinitely increase the duration
9115 // on a service that just occasionally gets killed (which is
9116 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009117 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009118 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009119 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009121 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009122 if (r.restartDelay < minDuration) {
9123 r.restartDelay = minDuration;
9124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 }
9126 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009127
9128 r.nextRestartTime = now + r.restartDelay;
9129
9130 // Make sure that we don't end up restarting a bunch of services
9131 // all at the same time.
9132 boolean repeat;
9133 do {
9134 repeat = false;
9135 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9136 ServiceRecord r2 = mRestartingServices.get(i);
9137 if (r2 != r && r.nextRestartTime
9138 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9139 && r.nextRestartTime
9140 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9141 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9142 r.restartDelay = r.nextRestartTime - now;
9143 repeat = true;
9144 break;
9145 }
9146 }
9147 } while (repeat);
9148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009149 if (!mRestartingServices.contains(r)) {
9150 mRestartingServices.add(r);
9151 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009152
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009153 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009155 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009156 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009157 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009158 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009159 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009160 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009161 r.shortName, r.restartDelay);
9162
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009163 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009164 }
9165
9166 final void performServiceRestartLocked(ServiceRecord r) {
9167 if (!mRestartingServices.contains(r)) {
9168 return;
9169 }
9170 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9171 }
9172
9173 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9174 if (r.restartDelay == 0) {
9175 return false;
9176 }
9177 r.resetRestartCounter();
9178 mRestartingServices.remove(r);
9179 mHandler.removeCallbacks(r.restarter);
9180 return true;
9181 }
9182
9183 private final boolean bringUpServiceLocked(ServiceRecord r,
9184 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009185 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009186 //r.dump(" ");
9187
Dianne Hackborn36124872009-10-08 16:22:03 -07009188 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 sendServiceArgsLocked(r, false);
9190 return true;
9191 }
9192
9193 if (!whileRestarting && r.restartDelay > 0) {
9194 // If waiting for a restart, then do nothing.
9195 return true;
9196 }
9197
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009198 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009199
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009200 // We are now bringing the service up, so no longer in the
9201 // restarting state.
9202 mRestartingServices.remove(r);
9203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009204 final String appName = r.processName;
9205 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9206 if (app != null && app.thread != null) {
9207 try {
9208 realStartServiceLocked(r, app);
9209 return true;
9210 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009211 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009212 }
9213
9214 // If a dead object exception was thrown -- fall through to
9215 // restart the application.
9216 }
9217
Dianne Hackborn36124872009-10-08 16:22:03 -07009218 // Not running -- get it started, and enqueue this service record
9219 // to be executed when the app comes up.
9220 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9221 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009222 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009223 + r.appInfo.packageName + "/"
9224 + r.appInfo.uid + " for service "
9225 + r.intent.getIntent() + ": process is bad");
9226 bringDownServiceLocked(r, true);
9227 return false;
9228 }
9229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009230 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 mPendingServices.add(r);
9232 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009234 return true;
9235 }
9236
9237 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009238 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009239 //r.dump(" ");
9240
9241 // Does it still need to run?
9242 if (!force && r.startRequested) {
9243 return;
9244 }
9245 if (r.connections.size() > 0) {
9246 if (!force) {
9247 // XXX should probably keep a count of the number of auto-create
9248 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009249 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009251 ArrayList<ConnectionRecord> cr = it.next();
9252 for (int i=0; i<cr.size(); i++) {
9253 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9254 return;
9255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009256 }
9257 }
9258 }
9259
9260 // Report to all of the connections that the service is no longer
9261 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009262 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009263 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009264 ArrayList<ConnectionRecord> c = it.next();
9265 for (int i=0; i<c.size(); i++) {
9266 try {
9267 c.get(i).conn.connected(r.name, null);
9268 } catch (Exception e) {
9269 Slog.w(TAG, "Failure disconnecting service " + r.name +
9270 " to connection " + c.get(i).conn.asBinder() +
9271 " (in " + c.get(i).binding.client.processName + ")", e);
9272 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009273 }
9274 }
9275 }
9276
9277 // Tell the service that it has been unbound.
9278 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9279 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9280 while (it.hasNext()) {
9281 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009282 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009283 + ": hasBound=" + ibr.hasBound);
9284 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9285 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009286 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009287 updateOomAdjLocked(r.app);
9288 ibr.hasBound = false;
9289 r.app.thread.scheduleUnbindService(r,
9290 ibr.intent.getIntent());
9291 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009292 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009293 + r.shortName, e);
9294 serviceDoneExecutingLocked(r, true);
9295 }
9296 }
9297 }
9298 }
9299
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009300 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009301 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009302 System.identityHashCode(r), r.shortName,
9303 (r.app != null) ? r.app.pid : -1);
9304
9305 mServices.remove(r.name);
9306 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009307 r.totalRestartCount = 0;
9308 unscheduleServiceRestartLocked(r);
9309
9310 // Also make sure it is not on the pending list.
9311 int N = mPendingServices.size();
9312 for (int i=0; i<N; i++) {
9313 if (mPendingServices.get(i) == r) {
9314 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009315 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009316 i--;
9317 N--;
9318 }
9319 }
9320
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009321 r.cancelNotification();
9322 r.isForeground = false;
9323 r.foregroundId = 0;
9324 r.foregroundNoti = null;
9325
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009326 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009327 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009328 r.pendingStarts.clear();
9329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009330 if (r.app != null) {
9331 synchronized (r.stats.getBatteryStats()) {
9332 r.stats.stopLaunchedLocked();
9333 }
9334 r.app.services.remove(r);
9335 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009336 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009337 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009338 mStoppingServices.add(r);
9339 updateOomAdjLocked(r.app);
9340 r.app.thread.scheduleStopService(r);
9341 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009342 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009343 + r.shortName, e);
9344 serviceDoneExecutingLocked(r, true);
9345 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009346 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009347 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009348 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009349 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009350 }
9351 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009352 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009353 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009354 }
9355 }
9356
9357 ComponentName startServiceLocked(IApplicationThread caller,
9358 Intent service, String resolvedType,
9359 int callingPid, int callingUid) {
9360 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009361 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009362 + " type=" + resolvedType + " args=" + service.getExtras());
9363
9364 if (caller != null) {
9365 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9366 if (callerApp == null) {
9367 throw new SecurityException(
9368 "Unable to find app for caller " + caller
9369 + " (pid=" + Binder.getCallingPid()
9370 + ") when starting service " + service);
9371 }
9372 }
9373
9374 ServiceLookupResult res =
9375 retrieveServiceLocked(service, resolvedType,
9376 callingPid, callingUid);
9377 if (res == null) {
9378 return null;
9379 }
9380 if (res.record == null) {
9381 return new ComponentName("!", res.permission != null
9382 ? res.permission : "private to package");
9383 }
9384 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009385 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9386 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009387 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009388 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009389 }
9390 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009391 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009392 r.lastStartId++;
9393 if (r.lastStartId < 1) {
9394 r.lastStartId = 1;
9395 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009396 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9397 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009398 r.lastActivity = SystemClock.uptimeMillis();
9399 synchronized (r.stats.getBatteryStats()) {
9400 r.stats.startRunningLocked();
9401 }
9402 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9403 return new ComponentName("!", "Service process is bad");
9404 }
9405 return r.name;
9406 }
9407 }
9408
9409 public ComponentName startService(IApplicationThread caller, Intent service,
9410 String resolvedType) {
9411 // Refuse possible leaked file descriptors
9412 if (service != null && service.hasFileDescriptors() == true) {
9413 throw new IllegalArgumentException("File descriptors passed in Intent");
9414 }
9415
9416 synchronized(this) {
9417 final int callingPid = Binder.getCallingPid();
9418 final int callingUid = Binder.getCallingUid();
9419 final long origId = Binder.clearCallingIdentity();
9420 ComponentName res = startServiceLocked(caller, service,
9421 resolvedType, callingPid, callingUid);
9422 Binder.restoreCallingIdentity(origId);
9423 return res;
9424 }
9425 }
9426
9427 ComponentName startServiceInPackage(int uid,
9428 Intent service, String resolvedType) {
9429 synchronized(this) {
9430 final long origId = Binder.clearCallingIdentity();
9431 ComponentName res = startServiceLocked(null, service,
9432 resolvedType, -1, uid);
9433 Binder.restoreCallingIdentity(origId);
9434 return res;
9435 }
9436 }
9437
9438 public int stopService(IApplicationThread caller, Intent service,
9439 String resolvedType) {
9440 // Refuse possible leaked file descriptors
9441 if (service != null && service.hasFileDescriptors() == true) {
9442 throw new IllegalArgumentException("File descriptors passed in Intent");
9443 }
9444
9445 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009446 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009447 + " type=" + resolvedType);
9448
9449 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9450 if (caller != null && callerApp == null) {
9451 throw new SecurityException(
9452 "Unable to find app for caller " + caller
9453 + " (pid=" + Binder.getCallingPid()
9454 + ") when stopping service " + service);
9455 }
9456
9457 // If this service is active, make sure it is stopped.
9458 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9459 if (r != null) {
9460 if (r.record != null) {
9461 synchronized (r.record.stats.getBatteryStats()) {
9462 r.record.stats.stopRunningLocked();
9463 }
9464 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009465 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009466 final long origId = Binder.clearCallingIdentity();
9467 bringDownServiceLocked(r.record, false);
9468 Binder.restoreCallingIdentity(origId);
9469 return 1;
9470 }
9471 return -1;
9472 }
9473 }
9474
9475 return 0;
9476 }
9477
9478 public IBinder peekService(Intent service, String resolvedType) {
9479 // Refuse possible leaked file descriptors
9480 if (service != null && service.hasFileDescriptors() == true) {
9481 throw new IllegalArgumentException("File descriptors passed in Intent");
9482 }
9483
9484 IBinder ret = null;
9485
9486 synchronized(this) {
9487 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9488
9489 if (r != null) {
9490 // r.record is null if findServiceLocked() failed the caller permission check
9491 if (r.record == null) {
9492 throw new SecurityException(
9493 "Permission Denial: Accessing service " + r.record.name
9494 + " from pid=" + Binder.getCallingPid()
9495 + ", uid=" + Binder.getCallingUid()
9496 + " requires " + r.permission);
9497 }
9498 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9499 if (ib != null) {
9500 ret = ib.binder;
9501 }
9502 }
9503 }
9504
9505 return ret;
9506 }
9507
9508 public boolean stopServiceToken(ComponentName className, IBinder token,
9509 int startId) {
9510 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009511 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009512 + " " + token + " startId=" + startId);
9513 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009514 if (r != null) {
9515 if (startId >= 0) {
9516 // Asked to only stop if done with all work. Note that
9517 // to avoid leaks, we will take this as dropping all
9518 // start items up to and including this one.
9519 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9520 if (si != null) {
9521 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009522 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9523 cur.removeUriPermissionsLocked();
9524 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009525 break;
9526 }
9527 }
9528 }
9529
9530 if (r.lastStartId != startId) {
9531 return false;
9532 }
9533
9534 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009535 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009536 + " is last, but have " + r.deliveredStarts.size()
9537 + " remaining args");
9538 }
9539 }
9540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009541 synchronized (r.stats.getBatteryStats()) {
9542 r.stats.stopRunningLocked();
9543 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009544 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545 }
9546 final long origId = Binder.clearCallingIdentity();
9547 bringDownServiceLocked(r, false);
9548 Binder.restoreCallingIdentity(origId);
9549 return true;
9550 }
9551 }
9552 return false;
9553 }
9554
9555 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009556 int id, Notification notification, boolean removeNotification) {
9557 final long origId = Binder.clearCallingIdentity();
9558 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009559 synchronized(this) {
9560 ServiceRecord r = findServiceLocked(className, token);
9561 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009562 if (id != 0) {
9563 if (notification == null) {
9564 throw new IllegalArgumentException("null notification");
9565 }
9566 if (r.foregroundId != id) {
9567 r.cancelNotification();
9568 r.foregroundId = id;
9569 }
9570 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9571 r.foregroundNoti = notification;
9572 r.isForeground = true;
9573 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009574 if (r.app != null) {
9575 updateServiceForegroundLocked(r.app, true);
9576 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009577 } else {
9578 if (r.isForeground) {
9579 r.isForeground = false;
9580 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009581 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009582 updateServiceForegroundLocked(r.app, true);
9583 }
9584 }
9585 if (removeNotification) {
9586 r.cancelNotification();
9587 r.foregroundId = 0;
9588 r.foregroundNoti = null;
9589 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009590 }
9591 }
9592 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009593 } finally {
9594 Binder.restoreCallingIdentity(origId);
9595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009596 }
9597
9598 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9599 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009600 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009601 if (sr.isForeground) {
9602 anyForeground = true;
9603 break;
9604 }
9605 }
9606 if (anyForeground != proc.foregroundServices) {
9607 proc.foregroundServices = anyForeground;
9608 if (oomAdj) {
9609 updateOomAdjLocked();
9610 }
9611 }
9612 }
9613
9614 public int bindService(IApplicationThread caller, IBinder token,
9615 Intent service, String resolvedType,
9616 IServiceConnection connection, int flags) {
9617 // Refuse possible leaked file descriptors
9618 if (service != null && service.hasFileDescriptors() == true) {
9619 throw new IllegalArgumentException("File descriptors passed in Intent");
9620 }
9621
9622 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009623 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009624 + " type=" + resolvedType + " conn=" + connection.asBinder()
9625 + " flags=0x" + Integer.toHexString(flags));
9626 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9627 if (callerApp == null) {
9628 throw new SecurityException(
9629 "Unable to find app for caller " + caller
9630 + " (pid=" + Binder.getCallingPid()
9631 + ") when binding service " + service);
9632 }
9633
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009634 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009635 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009636 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009637 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009638 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009639 return 0;
9640 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009641 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009642 }
9643
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009644 int clientLabel = 0;
9645 PendingIntent clientIntent = null;
9646
9647 if (callerApp.info.uid == Process.SYSTEM_UID) {
9648 // Hacky kind of thing -- allow system stuff to tell us
9649 // what they are, so we can report this elsewhere for
9650 // others to know why certain services are running.
9651 try {
9652 clientIntent = (PendingIntent)service.getParcelableExtra(
9653 Intent.EXTRA_CLIENT_INTENT);
9654 } catch (RuntimeException e) {
9655 }
9656 if (clientIntent != null) {
9657 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9658 if (clientLabel != 0) {
9659 // There are no useful extras in the intent, trash them.
9660 // System code calling with this stuff just needs to know
9661 // this will happen.
9662 service = service.cloneFilter();
9663 }
9664 }
9665 }
9666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667 ServiceLookupResult res =
9668 retrieveServiceLocked(service, resolvedType,
9669 Binder.getCallingPid(), Binder.getCallingUid());
9670 if (res == null) {
9671 return 0;
9672 }
9673 if (res.record == null) {
9674 return -1;
9675 }
9676 ServiceRecord s = res.record;
9677
9678 final long origId = Binder.clearCallingIdentity();
9679
9680 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009681 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009682 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009683 }
9684
9685 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9686 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009687 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009688
9689 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009690 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9691 if (clist == null) {
9692 clist = new ArrayList<ConnectionRecord>();
9693 s.connections.put(binder, clist);
9694 }
9695 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009696 b.connections.add(c);
9697 if (activity != null) {
9698 if (activity.connections == null) {
9699 activity.connections = new HashSet<ConnectionRecord>();
9700 }
9701 activity.connections.add(c);
9702 }
9703 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009704 clist = mServiceConnections.get(binder);
9705 if (clist == null) {
9706 clist = new ArrayList<ConnectionRecord>();
9707 mServiceConnections.put(binder, clist);
9708 }
9709 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009710
9711 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9712 s.lastActivity = SystemClock.uptimeMillis();
9713 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9714 return 0;
9715 }
9716 }
9717
9718 if (s.app != null) {
9719 // This could have made the service more important.
9720 updateOomAdjLocked(s.app);
9721 }
9722
Joe Onorato8a9b2202010-02-26 18:56:32 -08009723 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009724 + ": received=" + b.intent.received
9725 + " apps=" + b.intent.apps.size()
9726 + " doRebind=" + b.intent.doRebind);
9727
9728 if (s.app != null && b.intent.received) {
9729 // Service is already running, so we can immediately
9730 // publish the connection.
9731 try {
9732 c.conn.connected(s.name, b.intent.binder);
9733 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009734 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009735 + " to connection " + c.conn.asBinder()
9736 + " (in " + c.binding.client.processName + ")", e);
9737 }
9738
9739 // If this is the first app connected back to this binding,
9740 // and the service had previously asked to be told when
9741 // rebound, then do so.
9742 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9743 requestServiceBindingLocked(s, b.intent, true);
9744 }
9745 } else if (!b.intent.requested) {
9746 requestServiceBindingLocked(s, b.intent, false);
9747 }
9748
9749 Binder.restoreCallingIdentity(origId);
9750 }
9751
9752 return 1;
9753 }
9754
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009755 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009756 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 IBinder binder = c.conn.asBinder();
9758 AppBindRecord b = c.binding;
9759 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009760 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9761 if (clist != null) {
9762 clist.remove(c);
9763 if (clist.size() == 0) {
9764 s.connections.remove(binder);
9765 }
9766 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009767 b.connections.remove(c);
9768 if (c.activity != null && c.activity != skipAct) {
9769 if (c.activity.connections != null) {
9770 c.activity.connections.remove(c);
9771 }
9772 }
9773 if (b.client != skipApp) {
9774 b.client.connections.remove(c);
9775 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009776 clist = mServiceConnections.get(binder);
9777 if (clist != null) {
9778 clist.remove(c);
9779 if (clist.size() == 0) {
9780 mServiceConnections.remove(binder);
9781 }
9782 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009783
9784 if (b.connections.size() == 0) {
9785 b.intent.apps.remove(b.client);
9786 }
9787
Joe Onorato8a9b2202010-02-26 18:56:32 -08009788 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009789 + ": shouldUnbind=" + b.intent.hasBound);
9790 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9791 && b.intent.hasBound) {
9792 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009793 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794 updateOomAdjLocked(s.app);
9795 b.intent.hasBound = false;
9796 // Assume the client doesn't want to know about a rebind;
9797 // we will deal with that later if it asks for one.
9798 b.intent.doRebind = false;
9799 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9800 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009801 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009802 serviceDoneExecutingLocked(s, true);
9803 }
9804 }
9805
9806 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9807 bringDownServiceLocked(s, false);
9808 }
9809 }
9810
9811 public boolean unbindService(IServiceConnection connection) {
9812 synchronized (this) {
9813 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009814 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009815 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9816 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009817 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009818 + connection.asBinder());
9819 return false;
9820 }
9821
9822 final long origId = Binder.clearCallingIdentity();
9823
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009824 while (clist.size() > 0) {
9825 ConnectionRecord r = clist.get(0);
9826 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009827
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009828 if (r.binding.service.app != null) {
9829 // This could have made the service less important.
9830 updateOomAdjLocked(r.binding.service.app);
9831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832 }
9833
9834 Binder.restoreCallingIdentity(origId);
9835 }
9836
9837 return true;
9838 }
9839
9840 public void publishService(IBinder token, Intent intent, IBinder service) {
9841 // Refuse possible leaked file descriptors
9842 if (intent != null && intent.hasFileDescriptors() == true) {
9843 throw new IllegalArgumentException("File descriptors passed in Intent");
9844 }
9845
9846 synchronized(this) {
9847 if (!(token instanceof ServiceRecord)) {
9848 throw new IllegalArgumentException("Invalid service token");
9849 }
9850 ServiceRecord r = (ServiceRecord)token;
9851
9852 final long origId = Binder.clearCallingIdentity();
9853
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009854 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009855 + " " + intent + ": " + service);
9856 if (r != null) {
9857 Intent.FilterComparison filter
9858 = new Intent.FilterComparison(intent);
9859 IntentBindRecord b = r.bindings.get(filter);
9860 if (b != null && !b.received) {
9861 b.binder = service;
9862 b.requested = true;
9863 b.received = true;
9864 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009865 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009866 = r.connections.values().iterator();
9867 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009868 ArrayList<ConnectionRecord> clist = it.next();
9869 for (int i=0; i<clist.size(); i++) {
9870 ConnectionRecord c = clist.get(i);
9871 if (!filter.equals(c.binding.intent.intent)) {
9872 if (DEBUG_SERVICE) Slog.v(
9873 TAG, "Not publishing to: " + c);
9874 if (DEBUG_SERVICE) Slog.v(
9875 TAG, "Bound intent: " + c.binding.intent.intent);
9876 if (DEBUG_SERVICE) Slog.v(
9877 TAG, "Published intent: " + intent);
9878 continue;
9879 }
9880 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9881 try {
9882 c.conn.connected(r.name, service);
9883 } catch (Exception e) {
9884 Slog.w(TAG, "Failure sending service " + r.name +
9885 " to connection " + c.conn.asBinder() +
9886 " (in " + c.binding.client.processName + ")", e);
9887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009888 }
9889 }
9890 }
9891 }
9892
9893 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9894
9895 Binder.restoreCallingIdentity(origId);
9896 }
9897 }
9898 }
9899
9900 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9901 // Refuse possible leaked file descriptors
9902 if (intent != null && intent.hasFileDescriptors() == true) {
9903 throw new IllegalArgumentException("File descriptors passed in Intent");
9904 }
9905
9906 synchronized(this) {
9907 if (!(token instanceof ServiceRecord)) {
9908 throw new IllegalArgumentException("Invalid service token");
9909 }
9910 ServiceRecord r = (ServiceRecord)token;
9911
9912 final long origId = Binder.clearCallingIdentity();
9913
9914 if (r != null) {
9915 Intent.FilterComparison filter
9916 = new Intent.FilterComparison(intent);
9917 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009918 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009919 + " at " + b + ": apps="
9920 + (b != null ? b.apps.size() : 0));
9921 if (b != null) {
9922 if (b.apps.size() > 0) {
9923 // Applications have already bound since the last
9924 // unbind, so just rebind right here.
9925 requestServiceBindingLocked(r, b, true);
9926 } else {
9927 // Note to tell the service the next time there is
9928 // a new client.
9929 b.doRebind = true;
9930 }
9931 }
9932
9933 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9934
9935 Binder.restoreCallingIdentity(origId);
9936 }
9937 }
9938 }
9939
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009940 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009941 synchronized(this) {
9942 if (!(token instanceof ServiceRecord)) {
9943 throw new IllegalArgumentException("Invalid service token");
9944 }
9945 ServiceRecord r = (ServiceRecord)token;
9946 boolean inStopping = mStoppingServices.contains(token);
9947 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009948 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009949 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009950 + " with incorrect token: given " + token
9951 + ", expected " + r);
9952 return;
9953 }
9954
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009955 if (type == 1) {
9956 // This is a call from a service start... take care of
9957 // book-keeping.
9958 r.callStart = true;
9959 switch (res) {
9960 case Service.START_STICKY_COMPATIBILITY:
9961 case Service.START_STICKY: {
9962 // We are done with the associated start arguments.
9963 r.findDeliveredStart(startId, true);
9964 // Don't stop if killed.
9965 r.stopIfKilled = false;
9966 break;
9967 }
9968 case Service.START_NOT_STICKY: {
9969 // We are done with the associated start arguments.
9970 r.findDeliveredStart(startId, true);
9971 if (r.lastStartId == startId) {
9972 // There is no more work, and this service
9973 // doesn't want to hang around if killed.
9974 r.stopIfKilled = true;
9975 }
9976 break;
9977 }
9978 case Service.START_REDELIVER_INTENT: {
9979 // We'll keep this item until they explicitly
9980 // call stop for it, but keep track of the fact
9981 // that it was delivered.
9982 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9983 if (si != null) {
9984 si.deliveryCount = 0;
9985 si.doneExecutingCount++;
9986 // Don't stop if killed.
9987 r.stopIfKilled = true;
9988 }
9989 break;
9990 }
9991 default:
9992 throw new IllegalArgumentException(
9993 "Unknown service start result: " + res);
9994 }
9995 if (res == Service.START_STICKY_COMPATIBILITY) {
9996 r.callStart = false;
9997 }
9998 }
9999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000 final long origId = Binder.clearCallingIdentity();
10001 serviceDoneExecutingLocked(r, inStopping);
10002 Binder.restoreCallingIdentity(origId);
10003 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010004 Slog.w(TAG, "Done executing unknown service from pid "
10005 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 }
10007 }
10008 }
10009
10010 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010011 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10012 + ": nesting=" + r.executeNesting
10013 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010014 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010015 r.executeNesting--;
10016 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010017 if (DEBUG_SERVICE) Slog.v(TAG,
10018 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010019 r.app.executingServices.remove(r);
10020 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010021 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10022 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010023 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10024 }
10025 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010026 if (DEBUG_SERVICE) Slog.v(TAG,
10027 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010028 mStoppingServices.remove(r);
10029 }
10030 updateOomAdjLocked(r.app);
10031 }
10032 }
10033
10034 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010035 String anrMessage = null;
10036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010037 synchronized(this) {
10038 if (proc.executingServices.size() == 0 || proc.thread == null) {
10039 return;
10040 }
10041 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10042 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10043 ServiceRecord timeout = null;
10044 long nextTime = 0;
10045 while (it.hasNext()) {
10046 ServiceRecord sr = it.next();
10047 if (sr.executingStart < maxTime) {
10048 timeout = sr;
10049 break;
10050 }
10051 if (sr.executingStart > nextTime) {
10052 nextTime = sr.executingStart;
10053 }
10054 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010055 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010056 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010057 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010058 } else {
10059 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10060 msg.obj = proc;
10061 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10062 }
10063 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010064
10065 if (anrMessage != null) {
10066 appNotResponding(proc, null, null, anrMessage);
10067 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010068 }
10069
10070 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010071 // BACKUP AND RESTORE
10072 // =========================================================
10073
10074 // Cause the target app to be launched if necessary and its backup agent
10075 // instantiated. The backup agent will invoke backupAgentCreated() on the
10076 // activity manager to announce its creation.
10077 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010078 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010079 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10080
10081 synchronized(this) {
10082 // !!! TODO: currently no check here that we're already bound
10083 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10084 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10085 synchronized (stats) {
10086 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10087 }
10088
10089 BackupRecord r = new BackupRecord(ss, app, backupMode);
10090 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10091 // startProcessLocked() returns existing proc's record if it's already running
10092 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010093 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010094 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010095 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010096 return false;
10097 }
10098
10099 r.app = proc;
10100 mBackupTarget = r;
10101 mBackupAppName = app.packageName;
10102
Christopher Tate6fa95972009-06-05 18:43:55 -070010103 // Try not to kill the process during backup
10104 updateOomAdjLocked(proc);
10105
Christopher Tate181fafa2009-05-14 11:12:14 -070010106 // If the process is already attached, schedule the creation of the backup agent now.
10107 // If it is not yet live, this will be done when it attaches to the framework.
10108 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010109 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010110 try {
10111 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10112 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010113 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010114 }
10115 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010116 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010117 }
10118 // Invariants: at this point, the target app process exists and the application
10119 // is either already running or in the process of coming up. mBackupTarget and
10120 // mBackupAppName describe the app, so that when it binds back to the AM we
10121 // know that it's scheduled for a backup-agent operation.
10122 }
10123
10124 return true;
10125 }
10126
10127 // A backup agent has just come up
10128 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010129 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010130 + " = " + agent);
10131
10132 synchronized(this) {
10133 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010134 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010135 return;
10136 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010137 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010138
Dianne Hackborn06740692010-09-22 22:46:21 -070010139 long oldIdent = Binder.clearCallingIdentity();
10140 try {
10141 IBackupManager bm = IBackupManager.Stub.asInterface(
10142 ServiceManager.getService(Context.BACKUP_SERVICE));
10143 bm.agentConnected(agentPackageName, agent);
10144 } catch (RemoteException e) {
10145 // can't happen; the backup manager service is local
10146 } catch (Exception e) {
10147 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10148 e.printStackTrace();
10149 } finally {
10150 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010151 }
10152 }
10153
10154 // done with this agent
10155 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010156 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010157 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010158 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010159 return;
10160 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010161
10162 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010163 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010164 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010165 return;
10166 }
10167
Christopher Tate181fafa2009-05-14 11:12:14 -070010168 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010169 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010170 return;
10171 }
10172
Christopher Tate6fa95972009-06-05 18:43:55 -070010173 ProcessRecord proc = mBackupTarget.app;
10174 mBackupTarget = null;
10175 mBackupAppName = null;
10176
10177 // Not backing this app up any more; reset its OOM adjustment
10178 updateOomAdjLocked(proc);
10179
Christopher Tatec7b31e32009-06-10 15:49:30 -070010180 // If the app crashed during backup, 'thread' will be null here
10181 if (proc.thread != null) {
10182 try {
10183 proc.thread.scheduleDestroyBackupAgent(appInfo);
10184 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010185 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010186 e.printStackTrace();
10187 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010188 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010189 }
10190 }
10191 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010192 // BROADCASTS
10193 // =========================================================
10194
Josh Bartel7f208742010-02-25 11:01:44 -060010195 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010196 List cur) {
10197 final ContentResolver resolver = mContext.getContentResolver();
10198 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10199 if (list == null) {
10200 return cur;
10201 }
10202 int N = list.size();
10203 for (int i=0; i<N; i++) {
10204 Intent intent = list.get(i);
10205 if (filter.match(resolver, intent, true, TAG) >= 0) {
10206 if (cur == null) {
10207 cur = new ArrayList<Intent>();
10208 }
10209 cur.add(intent);
10210 }
10211 }
10212 return cur;
10213 }
10214
10215 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010216 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010217 + mBroadcastsScheduled);
10218
10219 if (mBroadcastsScheduled) {
10220 return;
10221 }
10222 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10223 mBroadcastsScheduled = true;
10224 }
10225
10226 public Intent registerReceiver(IApplicationThread caller,
10227 IIntentReceiver receiver, IntentFilter filter, String permission) {
10228 synchronized(this) {
10229 ProcessRecord callerApp = null;
10230 if (caller != null) {
10231 callerApp = getRecordForAppLocked(caller);
10232 if (callerApp == null) {
10233 throw new SecurityException(
10234 "Unable to find app for caller " + caller
10235 + " (pid=" + Binder.getCallingPid()
10236 + ") when registering receiver " + receiver);
10237 }
10238 }
10239
10240 List allSticky = null;
10241
10242 // Look for any matching sticky broadcasts...
10243 Iterator actions = filter.actionsIterator();
10244 if (actions != null) {
10245 while (actions.hasNext()) {
10246 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010247 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010248 }
10249 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010250 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 }
10252
10253 // The first sticky in the list is returned directly back to
10254 // the client.
10255 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10256
Joe Onorato8a9b2202010-02-26 18:56:32 -080010257 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010258 + ": " + sticky);
10259
10260 if (receiver == null) {
10261 return sticky;
10262 }
10263
10264 ReceiverList rl
10265 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10266 if (rl == null) {
10267 rl = new ReceiverList(this, callerApp,
10268 Binder.getCallingPid(),
10269 Binder.getCallingUid(), receiver);
10270 if (rl.app != null) {
10271 rl.app.receivers.add(rl);
10272 } else {
10273 try {
10274 receiver.asBinder().linkToDeath(rl, 0);
10275 } catch (RemoteException e) {
10276 return sticky;
10277 }
10278 rl.linkedToDeath = true;
10279 }
10280 mRegisteredReceivers.put(receiver.asBinder(), rl);
10281 }
10282 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10283 rl.add(bf);
10284 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010285 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010286 }
10287 mReceiverResolver.addFilter(bf);
10288
10289 // Enqueue broadcasts for all existing stickies that match
10290 // this filter.
10291 if (allSticky != null) {
10292 ArrayList receivers = new ArrayList();
10293 receivers.add(bf);
10294
10295 int N = allSticky.size();
10296 for (int i=0; i<N; i++) {
10297 Intent intent = (Intent)allSticky.get(i);
10298 BroadcastRecord r = new BroadcastRecord(intent, null,
10299 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010300 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 if (mParallelBroadcasts.size() == 0) {
10302 scheduleBroadcastsLocked();
10303 }
10304 mParallelBroadcasts.add(r);
10305 }
10306 }
10307
10308 return sticky;
10309 }
10310 }
10311
10312 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010313 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314
10315 boolean doNext = false;
10316
10317 synchronized(this) {
10318 ReceiverList rl
10319 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10320 if (rl != null) {
10321 if (rl.curBroadcast != null) {
10322 BroadcastRecord r = rl.curBroadcast;
10323 doNext = finishReceiverLocked(
10324 receiver.asBinder(), r.resultCode, r.resultData,
10325 r.resultExtras, r.resultAbort, true);
10326 }
10327
10328 if (rl.app != null) {
10329 rl.app.receivers.remove(rl);
10330 }
10331 removeReceiverLocked(rl);
10332 if (rl.linkedToDeath) {
10333 rl.linkedToDeath = false;
10334 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10335 }
10336 }
10337 }
10338
10339 if (!doNext) {
10340 return;
10341 }
10342
10343 final long origId = Binder.clearCallingIdentity();
10344 processNextBroadcast(false);
10345 trimApplications();
10346 Binder.restoreCallingIdentity(origId);
10347 }
10348
10349 void removeReceiverLocked(ReceiverList rl) {
10350 mRegisteredReceivers.remove(rl.receiver.asBinder());
10351 int N = rl.size();
10352 for (int i=0; i<N; i++) {
10353 mReceiverResolver.removeFilter(rl.get(i));
10354 }
10355 }
10356
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010357 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10358 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10359 ProcessRecord r = mLruProcesses.get(i);
10360 if (r.thread != null) {
10361 try {
10362 r.thread.dispatchPackageBroadcast(cmd, packages);
10363 } catch (RemoteException ex) {
10364 }
10365 }
10366 }
10367 }
10368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010369 private final int broadcastIntentLocked(ProcessRecord callerApp,
10370 String callerPackage, Intent intent, String resolvedType,
10371 IIntentReceiver resultTo, int resultCode, String resultData,
10372 Bundle map, String requiredPermission,
10373 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10374 intent = new Intent(intent);
10375
Joe Onorato8a9b2202010-02-26 18:56:32 -080010376 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010377 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10378 + " ordered=" + ordered);
10379 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010380 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010381 }
10382
10383 // Handle special intents: if this broadcast is from the package
10384 // manager about a package being removed, we need to remove all of
10385 // its activities from the history stack.
10386 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10387 intent.getAction());
10388 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10389 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010390 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010391 || uidRemoved) {
10392 if (checkComponentPermission(
10393 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10394 callingPid, callingUid, -1)
10395 == PackageManager.PERMISSION_GRANTED) {
10396 if (uidRemoved) {
10397 final Bundle intentExtras = intent.getExtras();
10398 final int uid = intentExtras != null
10399 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10400 if (uid >= 0) {
10401 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10402 synchronized (bs) {
10403 bs.removeUidStatsLocked(uid);
10404 }
10405 }
10406 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010407 // If resources are unvailble just force stop all
10408 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010409 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010410 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10411 if (list != null && (list.length > 0)) {
10412 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010413 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010414 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010415 sendPackageBroadcastLocked(
10416 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010417 }
10418 } else {
10419 Uri data = intent.getData();
10420 String ssp;
10421 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10422 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10423 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010424 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010425 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010426 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10427 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10428 new String[] {ssp});
10429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430 }
10431 }
10432 }
10433 } else {
10434 String msg = "Permission Denial: " + intent.getAction()
10435 + " broadcast from " + callerPackage + " (pid=" + callingPid
10436 + ", uid=" + callingUid + ")"
10437 + " requires "
10438 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010439 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010440 throw new SecurityException(msg);
10441 }
10442 }
10443
10444 /*
10445 * If this is the time zone changed action, queue up a message that will reset the timezone
10446 * of all currently running processes. This message will get queued up before the broadcast
10447 * happens.
10448 */
10449 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10450 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10451 }
10452
Robert Greenwalt03595d02010-11-02 14:08:23 -070010453 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10454 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10455 }
10456
Robert Greenwalt434203a2010-10-11 16:00:27 -070010457 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10458 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10459 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10460 }
10461
Dianne Hackborn854060af2009-07-09 18:14:31 -070010462 /*
10463 * Prevent non-system code (defined here to be non-persistent
10464 * processes) from sending protected broadcasts.
10465 */
10466 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10467 || callingUid == Process.SHELL_UID || callingUid == 0) {
10468 // Always okay.
10469 } else if (callerApp == null || !callerApp.persistent) {
10470 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010471 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010472 intent.getAction())) {
10473 String msg = "Permission Denial: not allowed to send broadcast "
10474 + intent.getAction() + " from pid="
10475 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010476 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010477 throw new SecurityException(msg);
10478 }
10479 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010480 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010481 return BROADCAST_SUCCESS;
10482 }
10483 }
10484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010485 // Add to the sticky list if requested.
10486 if (sticky) {
10487 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10488 callingPid, callingUid)
10489 != PackageManager.PERMISSION_GRANTED) {
10490 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10491 + callingPid + ", uid=" + callingUid
10492 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010493 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010494 throw new SecurityException(msg);
10495 }
10496 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010497 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010498 + " and enforce permission " + requiredPermission);
10499 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10500 }
10501 if (intent.getComponent() != null) {
10502 throw new SecurityException(
10503 "Sticky broadcasts can't target a specific component");
10504 }
10505 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10506 if (list == null) {
10507 list = new ArrayList<Intent>();
10508 mStickyBroadcasts.put(intent.getAction(), list);
10509 }
10510 int N = list.size();
10511 int i;
10512 for (i=0; i<N; i++) {
10513 if (intent.filterEquals(list.get(i))) {
10514 // This sticky already exists, replace it.
10515 list.set(i, new Intent(intent));
10516 break;
10517 }
10518 }
10519 if (i >= N) {
10520 list.add(new Intent(intent));
10521 }
10522 }
10523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010524 // Figure out who all will receive this broadcast.
10525 List receivers = null;
10526 List<BroadcastFilter> registeredReceivers = null;
10527 try {
10528 if (intent.getComponent() != null) {
10529 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010530 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010531 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010532 if (ai != null) {
10533 receivers = new ArrayList();
10534 ResolveInfo ri = new ResolveInfo();
10535 ri.activityInfo = ai;
10536 receivers.add(ri);
10537 }
10538 } else {
10539 // Need to resolve the intent to interested receivers...
10540 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10541 == 0) {
10542 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010543 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010544 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010545 }
Mihai Preda074edef2009-05-18 17:13:31 +020010546 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010547 }
10548 } catch (RemoteException ex) {
10549 // pm is in same process, this will never happen.
10550 }
10551
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010552 final boolean replacePending =
10553 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10554
Joe Onorato8a9b2202010-02-26 18:56:32 -080010555 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010556 + " replacePending=" + replacePending);
10557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010558 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10559 if (!ordered && NR > 0) {
10560 // If we are not serializing this broadcast, then send the
10561 // registered receivers separately so they don't wait for the
10562 // components to be launched.
10563 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10564 callerPackage, callingPid, callingUid, requiredPermission,
10565 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010566 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010567 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568 TAG, "Enqueueing parallel broadcast " + r
10569 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010570 boolean replaced = false;
10571 if (replacePending) {
10572 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10573 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010574 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010575 "***** DROPPING PARALLEL: " + intent);
10576 mParallelBroadcasts.set(i, r);
10577 replaced = true;
10578 break;
10579 }
10580 }
10581 }
10582 if (!replaced) {
10583 mParallelBroadcasts.add(r);
10584 scheduleBroadcastsLocked();
10585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010586 registeredReceivers = null;
10587 NR = 0;
10588 }
10589
10590 // Merge into one list.
10591 int ir = 0;
10592 if (receivers != null) {
10593 // A special case for PACKAGE_ADDED: do not allow the package
10594 // being added to see this broadcast. This prevents them from
10595 // using this as a back door to get run as soon as they are
10596 // installed. Maybe in the future we want to have a special install
10597 // broadcast or such for apps, but we'd like to deliberately make
10598 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010599 String skipPackages[] = null;
10600 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10601 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10602 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10603 Uri data = intent.getData();
10604 if (data != null) {
10605 String pkgName = data.getSchemeSpecificPart();
10606 if (pkgName != null) {
10607 skipPackages = new String[] { pkgName };
10608 }
10609 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010610 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010611 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010612 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010613 if (skipPackages != null && (skipPackages.length > 0)) {
10614 for (String skipPackage : skipPackages) {
10615 if (skipPackage != null) {
10616 int NT = receivers.size();
10617 for (int it=0; it<NT; it++) {
10618 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10619 if (curt.activityInfo.packageName.equals(skipPackage)) {
10620 receivers.remove(it);
10621 it--;
10622 NT--;
10623 }
10624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010625 }
10626 }
10627 }
10628
10629 int NT = receivers != null ? receivers.size() : 0;
10630 int it = 0;
10631 ResolveInfo curt = null;
10632 BroadcastFilter curr = null;
10633 while (it < NT && ir < NR) {
10634 if (curt == null) {
10635 curt = (ResolveInfo)receivers.get(it);
10636 }
10637 if (curr == null) {
10638 curr = registeredReceivers.get(ir);
10639 }
10640 if (curr.getPriority() >= curt.priority) {
10641 // Insert this broadcast record into the final list.
10642 receivers.add(it, curr);
10643 ir++;
10644 curr = null;
10645 it++;
10646 NT++;
10647 } else {
10648 // Skip to the next ResolveInfo in the final list.
10649 it++;
10650 curt = null;
10651 }
10652 }
10653 }
10654 while (ir < NR) {
10655 if (receivers == null) {
10656 receivers = new ArrayList();
10657 }
10658 receivers.add(registeredReceivers.get(ir));
10659 ir++;
10660 }
10661
10662 if ((receivers != null && receivers.size() > 0)
10663 || resultTo != null) {
10664 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10665 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010666 receivers, resultTo, resultCode, resultData, map, ordered,
10667 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010668 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010669 TAG, "Enqueueing ordered broadcast " + r
10670 + ": prev had " + mOrderedBroadcasts.size());
10671 if (DEBUG_BROADCAST) {
10672 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010673 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010674 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010675 boolean replaced = false;
10676 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010677 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010678 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010679 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010680 "***** DROPPING ORDERED: " + intent);
10681 mOrderedBroadcasts.set(i, r);
10682 replaced = true;
10683 break;
10684 }
10685 }
10686 }
10687 if (!replaced) {
10688 mOrderedBroadcasts.add(r);
10689 scheduleBroadcastsLocked();
10690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010691 }
10692
10693 return BROADCAST_SUCCESS;
10694 }
10695
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010696 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010697 // Refuse possible leaked file descriptors
10698 if (intent != null && intent.hasFileDescriptors() == true) {
10699 throw new IllegalArgumentException("File descriptors passed in Intent");
10700 }
10701
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010702 int flags = intent.getFlags();
10703
10704 if (!mProcessesReady) {
10705 // if the caller really truly claims to know what they're doing, go
10706 // ahead and allow the broadcast without launching any receivers
10707 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10708 intent = new Intent(intent);
10709 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10710 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10711 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10712 + " before boot completion");
10713 throw new IllegalStateException("Cannot broadcast before boot completed");
10714 }
10715 }
10716
10717 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10718 throw new IllegalArgumentException(
10719 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10720 }
10721
10722 return intent;
10723 }
10724
10725 public final int broadcastIntent(IApplicationThread caller,
10726 Intent intent, String resolvedType, IIntentReceiver resultTo,
10727 int resultCode, String resultData, Bundle map,
10728 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010729 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010730 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010732 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10733 final int callingPid = Binder.getCallingPid();
10734 final int callingUid = Binder.getCallingUid();
10735 final long origId = Binder.clearCallingIdentity();
10736 int res = broadcastIntentLocked(callerApp,
10737 callerApp != null ? callerApp.info.packageName : null,
10738 intent, resolvedType, resultTo,
10739 resultCode, resultData, map, requiredPermission, serialized,
10740 sticky, callingPid, callingUid);
10741 Binder.restoreCallingIdentity(origId);
10742 return res;
10743 }
10744 }
10745
10746 int broadcastIntentInPackage(String packageName, int uid,
10747 Intent intent, String resolvedType, IIntentReceiver resultTo,
10748 int resultCode, String resultData, Bundle map,
10749 String requiredPermission, boolean serialized, boolean sticky) {
10750 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010751 intent = verifyBroadcastLocked(intent);
10752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753 final long origId = Binder.clearCallingIdentity();
10754 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10755 resultTo, resultCode, resultData, map, requiredPermission,
10756 serialized, sticky, -1, uid);
10757 Binder.restoreCallingIdentity(origId);
10758 return res;
10759 }
10760 }
10761
10762 public final void unbroadcastIntent(IApplicationThread caller,
10763 Intent intent) {
10764 // Refuse possible leaked file descriptors
10765 if (intent != null && intent.hasFileDescriptors() == true) {
10766 throw new IllegalArgumentException("File descriptors passed in Intent");
10767 }
10768
10769 synchronized(this) {
10770 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10771 != PackageManager.PERMISSION_GRANTED) {
10772 String msg = "Permission Denial: unbroadcastIntent() from pid="
10773 + Binder.getCallingPid()
10774 + ", uid=" + Binder.getCallingUid()
10775 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010776 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010777 throw new SecurityException(msg);
10778 }
10779 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10780 if (list != null) {
10781 int N = list.size();
10782 int i;
10783 for (i=0; i<N; i++) {
10784 if (intent.filterEquals(list.get(i))) {
10785 list.remove(i);
10786 break;
10787 }
10788 }
10789 }
10790 }
10791 }
10792
10793 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10794 String resultData, Bundle resultExtras, boolean resultAbort,
10795 boolean explicit) {
10796 if (mOrderedBroadcasts.size() == 0) {
10797 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010798 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010799 }
10800 return false;
10801 }
10802 BroadcastRecord r = mOrderedBroadcasts.get(0);
10803 if (r.receiver == null) {
10804 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010805 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010806 }
10807 return false;
10808 }
10809 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010810 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010811 return false;
10812 }
10813 int state = r.state;
10814 r.state = r.IDLE;
10815 if (state == r.IDLE) {
10816 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010817 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010818 }
10819 }
10820 r.receiver = null;
10821 r.intent.setComponent(null);
10822 if (r.curApp != null) {
10823 r.curApp.curReceiver = null;
10824 }
10825 if (r.curFilter != null) {
10826 r.curFilter.receiverList.curBroadcast = null;
10827 }
10828 r.curFilter = null;
10829 r.curApp = null;
10830 r.curComponent = null;
10831 r.curReceiver = null;
10832 mPendingBroadcast = null;
10833
10834 r.resultCode = resultCode;
10835 r.resultData = resultData;
10836 r.resultExtras = resultExtras;
10837 r.resultAbort = resultAbort;
10838
10839 // We will process the next receiver right now if this is finishing
10840 // an app receiver (which is always asynchronous) or after we have
10841 // come back from calling a receiver.
10842 return state == BroadcastRecord.APP_RECEIVE
10843 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10844 }
10845
10846 public void finishReceiver(IBinder who, int resultCode, String resultData,
10847 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010848 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010849
10850 // Refuse possible leaked file descriptors
10851 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10852 throw new IllegalArgumentException("File descriptors passed in Bundle");
10853 }
10854
10855 boolean doNext;
10856
10857 final long origId = Binder.clearCallingIdentity();
10858
10859 synchronized(this) {
10860 doNext = finishReceiverLocked(
10861 who, resultCode, resultData, resultExtras, resultAbort, true);
10862 }
10863
10864 if (doNext) {
10865 processNextBroadcast(false);
10866 }
10867 trimApplications();
10868
10869 Binder.restoreCallingIdentity(origId);
10870 }
10871
Jeff Brown4d94a762010-09-23 11:33:28 -070010872 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010873 if (r.nextReceiver > 0) {
10874 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10875 if (curReceiver instanceof BroadcastFilter) {
10876 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010877 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010878 System.identityHashCode(r),
10879 r.intent.getAction(),
10880 r.nextReceiver - 1,
10881 System.identityHashCode(bf));
10882 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010883 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010884 System.identityHashCode(r),
10885 r.intent.getAction(),
10886 r.nextReceiver - 1,
10887 ((ResolveInfo)curReceiver).toString());
10888 }
10889 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010890 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010892 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010893 System.identityHashCode(r),
10894 r.intent.getAction(),
10895 r.nextReceiver,
10896 "NONE");
10897 }
10898 }
10899
Jeff Brown4d94a762010-09-23 11:33:28 -070010900 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10901 if (! mPendingBroadcastTimeoutMessage) {
10902 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10903 mHandler.sendMessageAtTime(msg, timeoutTime);
10904 mPendingBroadcastTimeoutMessage = true;
10905 }
10906 }
10907
10908 private final void cancelBroadcastTimeoutLocked() {
10909 if (mPendingBroadcastTimeoutMessage) {
10910 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10911 mPendingBroadcastTimeoutMessage = false;
10912 }
10913 }
10914
10915 private final void broadcastTimeoutLocked(boolean fromMsg) {
10916 if (fromMsg) {
10917 mPendingBroadcastTimeoutMessage = false;
10918 }
10919
10920 if (mOrderedBroadcasts.size() == 0) {
10921 return;
10922 }
10923
10924 long now = SystemClock.uptimeMillis();
10925 BroadcastRecord r = mOrderedBroadcasts.get(0);
10926 if (fromMsg) {
10927 if (mDidDexOpt) {
10928 // Delay timeouts until dexopt finishes.
10929 mDidDexOpt = false;
10930 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10931 setBroadcastTimeoutLocked(timeoutTime);
10932 return;
10933 }
10934 if (! mProcessesReady) {
10935 // Only process broadcast timeouts if the system is ready. That way
10936 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10937 // to do heavy lifting for system up.
10938 return;
10939 }
10940
10941 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10942 if (timeoutTime > now) {
10943 // We can observe premature timeouts because we do not cancel and reset the
10944 // broadcast timeout message after each receiver finishes. Instead, we set up
10945 // an initial timeout then kick it down the road a little further as needed
10946 // when it expires.
10947 if (DEBUG_BROADCAST) Slog.v(TAG,
10948 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10949 + timeoutTime);
10950 setBroadcastTimeoutLocked(timeoutTime);
10951 return;
10952 }
10953 }
10954
10955 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10956 + ", started " + (now - r.receiverTime) + "ms ago");
10957 r.receiverTime = now;
10958 r.anrCount++;
10959
10960 // Current receiver has passed its expiration date.
10961 if (r.nextReceiver <= 0) {
10962 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10963 return;
10964 }
10965
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010966 ProcessRecord app = null;
10967 String anrMessage = null;
10968
Jeff Brown4d94a762010-09-23 11:33:28 -070010969 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10970 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10971 logBroadcastReceiverDiscardLocked(r);
10972 if (curReceiver instanceof BroadcastFilter) {
10973 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10974 if (bf.receiverList.pid != 0
10975 && bf.receiverList.pid != MY_PID) {
10976 synchronized (this.mPidsSelfLocked) {
10977 app = this.mPidsSelfLocked.get(
10978 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010981 } else {
10982 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010983 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010984
Jeff Brown4d94a762010-09-23 11:33:28 -070010985 if (app != null) {
10986 anrMessage = "Broadcast of " + r.intent.toString();
10987 }
10988
10989 if (mPendingBroadcast == r) {
10990 mPendingBroadcast = null;
10991 }
10992
10993 // Move on to the next receiver.
10994 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10995 r.resultExtras, r.resultAbort, true);
10996 scheduleBroadcastsLocked();
10997
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010998 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010999 // Post the ANR to the handler since we do not want to process ANRs while
11000 // potentially holding our lock.
11001 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011003 }
11004
11005 private final void processCurBroadcastLocked(BroadcastRecord r,
11006 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011007 if (DEBUG_BROADCAST) Slog.v(TAG,
11008 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011009 if (app.thread == null) {
11010 throw new RemoteException();
11011 }
11012 r.receiver = app.thread.asBinder();
11013 r.curApp = app;
11014 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011015 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016
11017 // Tell the application to launch this receiver.
11018 r.intent.setComponent(r.curComponent);
11019
11020 boolean started = false;
11021 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011022 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 "Delivering to component " + r.curComponent
11024 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011025 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011026 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11027 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011028 if (DEBUG_BROADCAST) Slog.v(TAG,
11029 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011030 started = true;
11031 } finally {
11032 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011033 if (DEBUG_BROADCAST) Slog.v(TAG,
11034 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011035 r.receiver = null;
11036 r.curApp = null;
11037 app.curReceiver = null;
11038 }
11039 }
11040
11041 }
11042
Jeff Brown4d94a762010-09-23 11:33:28 -070011043 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011044 Intent intent, int resultCode, String data, Bundle extras,
11045 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011046 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011047 if (app != null && app.thread != null) {
11048 // If we have an app thread, do the call through that so it is
11049 // correctly ordered with other one-way calls.
11050 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011051 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011053 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011054 }
11055 }
11056
Jeff Brown4d94a762010-09-23 11:33:28 -070011057 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011058 BroadcastFilter filter, boolean ordered) {
11059 boolean skip = false;
11060 if (filter.requiredPermission != null) {
11061 int perm = checkComponentPermission(filter.requiredPermission,
11062 r.callingPid, r.callingUid, -1);
11063 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011064 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 + r.intent.toString()
11066 + " from " + r.callerPackage + " (pid="
11067 + r.callingPid + ", uid=" + r.callingUid + ")"
11068 + " requires " + filter.requiredPermission
11069 + " due to registered receiver " + filter);
11070 skip = true;
11071 }
11072 }
11073 if (r.requiredPermission != null) {
11074 int perm = checkComponentPermission(r.requiredPermission,
11075 filter.receiverList.pid, filter.receiverList.uid, -1);
11076 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011077 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011078 + r.intent.toString()
11079 + " to " + filter.receiverList.app
11080 + " (pid=" + filter.receiverList.pid
11081 + ", uid=" + filter.receiverList.uid + ")"
11082 + " requires " + r.requiredPermission
11083 + " due to sender " + r.callerPackage
11084 + " (uid " + r.callingUid + ")");
11085 skip = true;
11086 }
11087 }
11088
11089 if (!skip) {
11090 // If this is not being sent as an ordered broadcast, then we
11091 // don't want to touch the fields that keep track of the current
11092 // state of ordered broadcasts.
11093 if (ordered) {
11094 r.receiver = filter.receiverList.receiver.asBinder();
11095 r.curFilter = filter;
11096 filter.receiverList.curBroadcast = r;
11097 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011098 if (filter.receiverList.app != null) {
11099 // Bump hosting application to no longer be in background
11100 // scheduling class. Note that we can't do that if there
11101 // isn't an app... but we can only be in that case for
11102 // things that directly call the IActivityManager API, which
11103 // are already core system stuff so don't matter for this.
11104 r.curApp = filter.receiverList.app;
11105 filter.receiverList.app.curReceiver = r;
11106 updateOomAdjLocked();
11107 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011108 }
11109 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011110 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011111 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011112 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011113 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011114 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011115 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011116 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011117 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011118 if (ordered) {
11119 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11120 }
11121 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011122 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011123 if (ordered) {
11124 r.receiver = null;
11125 r.curFilter = null;
11126 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011127 if (filter.receiverList.app != null) {
11128 filter.receiverList.app.curReceiver = null;
11129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011130 }
11131 }
11132 }
11133 }
11134
Dianne Hackborn12527f92009-11-11 17:39:50 -080011135 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11136 if (r.callingUid < 0) {
11137 // This was from a registerReceiver() call; ignore it.
11138 return;
11139 }
11140 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11141 MAX_BROADCAST_HISTORY-1);
11142 r.finishTime = SystemClock.uptimeMillis();
11143 mBroadcastHistory[0] = r;
11144 }
11145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011146 private final void processNextBroadcast(boolean fromMsg) {
11147 synchronized(this) {
11148 BroadcastRecord r;
11149
Joe Onorato8a9b2202010-02-26 18:56:32 -080011150 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011151 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011152 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011153
11154 updateCpuStats();
11155
11156 if (fromMsg) {
11157 mBroadcastsScheduled = false;
11158 }
11159
11160 // First, deliver any non-serialized broadcasts right away.
11161 while (mParallelBroadcasts.size() > 0) {
11162 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011163 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011165 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011166 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011167 for (int i=0; i<N; i++) {
11168 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011169 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011170 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011171 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011172 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011173 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011174 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011175 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011176 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011177 }
11178
11179 // Now take care of the next serialized one...
11180
11181 // If we are waiting for a process to come up to handle the next
11182 // broadcast, then do nothing at this point. Just in case, we
11183 // check that the process we're waiting for still exists.
11184 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011185 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011186 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011187 + mPendingBroadcast.curApp);
11188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011189
11190 boolean isDead;
11191 synchronized (mPidsSelfLocked) {
11192 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11193 }
11194 if (!isDead) {
11195 // It's still alive, so keep waiting
11196 return;
11197 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011198 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011200 mPendingBroadcast.state = BroadcastRecord.IDLE;
11201 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 mPendingBroadcast = null;
11203 }
11204 }
11205
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011206 boolean looped = false;
11207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011208 do {
11209 if (mOrderedBroadcasts.size() == 0) {
11210 // No more broadcasts pending, so all done!
11211 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011212 if (looped) {
11213 // If we had finished the last ordered broadcast, then
11214 // make sure all processes have correct oom and sched
11215 // adjustments.
11216 updateOomAdjLocked();
11217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011218 return;
11219 }
11220 r = mOrderedBroadcasts.get(0);
11221 boolean forceReceive = false;
11222
11223 // Ensure that even if something goes awry with the timeout
11224 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011225 // and continue to make progress.
11226 //
11227 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011228 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011229 // one time heavy lifting after system upgrades and can take
11230 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011231 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011232 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011233 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011234 if ((numReceivers > 0) &&
11235 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011236 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 + " now=" + now
11238 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011239 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011240 + " intent=" + r.intent
11241 + " numReceivers=" + numReceivers
11242 + " nextReceiver=" + r.nextReceiver
11243 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011244 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011245 forceReceive = true;
11246 r.state = BroadcastRecord.IDLE;
11247 }
11248 }
11249
11250 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011251 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011252 "processNextBroadcast() called when not idle (state="
11253 + r.state + ")");
11254 return;
11255 }
11256
11257 if (r.receivers == null || r.nextReceiver >= numReceivers
11258 || r.resultAbort || forceReceive) {
11259 // No more receivers for this broadcast! Send the final
11260 // result if requested...
11261 if (r.resultTo != null) {
11262 try {
11263 if (DEBUG_BROADCAST) {
11264 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011265 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 + " seq=" + seq + " app=" + r.callerApp);
11267 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011268 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011270 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011271 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011272 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011273 }
11274 }
11275
Joe Onorato8a9b2202010-02-26 18:56:32 -080011276 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011277 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278
Joe Onorato8a9b2202010-02-26 18:56:32 -080011279 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011280 + r);
11281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011283 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011284 mOrderedBroadcasts.remove(0);
11285 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011286 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011287 continue;
11288 }
11289 } while (r == null);
11290
11291 // Get the next receiver...
11292 int recIdx = r.nextReceiver++;
11293
11294 // Keep track of when this receiver started, and make sure there
11295 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011296 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011297 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011298 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011299
Joe Onorato8a9b2202010-02-26 18:56:32 -080011300 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011301 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011302 }
11303 if (! mPendingBroadcastTimeoutMessage) {
11304 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011305 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011306 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11307 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011308 }
11309
11310 Object nextReceiver = r.receivers.get(recIdx);
11311 if (nextReceiver instanceof BroadcastFilter) {
11312 // Simple case: this is a registered receiver who gets
11313 // a direct call.
11314 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011315 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011316 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011317 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011318 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011319 if (r.receiver == null || !r.ordered) {
11320 // The receiver has already finished, so schedule to
11321 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011322 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11323 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011324 r.state = BroadcastRecord.IDLE;
11325 scheduleBroadcastsLocked();
11326 }
11327 return;
11328 }
11329
11330 // Hard case: need to instantiate the receiver, possibly
11331 // starting its application process to host it.
11332
11333 ResolveInfo info =
11334 (ResolveInfo)nextReceiver;
11335
11336 boolean skip = false;
11337 int perm = checkComponentPermission(info.activityInfo.permission,
11338 r.callingPid, r.callingUid,
11339 info.activityInfo.exported
11340 ? -1 : info.activityInfo.applicationInfo.uid);
11341 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011342 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011343 + r.intent.toString()
11344 + " from " + r.callerPackage + " (pid=" + r.callingPid
11345 + ", uid=" + r.callingUid + ")"
11346 + " requires " + info.activityInfo.permission
11347 + " due to receiver " + info.activityInfo.packageName
11348 + "/" + info.activityInfo.name);
11349 skip = true;
11350 }
11351 if (r.callingUid != Process.SYSTEM_UID &&
11352 r.requiredPermission != null) {
11353 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011354 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011355 checkPermission(r.requiredPermission,
11356 info.activityInfo.applicationInfo.packageName);
11357 } catch (RemoteException e) {
11358 perm = PackageManager.PERMISSION_DENIED;
11359 }
11360 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011361 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 + r.intent + " to "
11363 + info.activityInfo.applicationInfo.packageName
11364 + " requires " + r.requiredPermission
11365 + " due to sender " + r.callerPackage
11366 + " (uid " + r.callingUid + ")");
11367 skip = true;
11368 }
11369 }
11370 if (r.curApp != null && r.curApp.crashing) {
11371 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011372 if (DEBUG_BROADCAST) Slog.v(TAG,
11373 "Skipping deliver ordered " + r + " to " + r.curApp
11374 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011375 skip = true;
11376 }
11377
11378 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011379 if (DEBUG_BROADCAST) Slog.v(TAG,
11380 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011381 r.receiver = null;
11382 r.curFilter = null;
11383 r.state = BroadcastRecord.IDLE;
11384 scheduleBroadcastsLocked();
11385 return;
11386 }
11387
11388 r.state = BroadcastRecord.APP_RECEIVE;
11389 String targetProcess = info.activityInfo.processName;
11390 r.curComponent = new ComponentName(
11391 info.activityInfo.applicationInfo.packageName,
11392 info.activityInfo.name);
11393 r.curReceiver = info.activityInfo;
11394
11395 // Is this receiver's application already running?
11396 ProcessRecord app = getProcessRecordLocked(targetProcess,
11397 info.activityInfo.applicationInfo.uid);
11398 if (app != null && app.thread != null) {
11399 try {
11400 processCurBroadcastLocked(r, app);
11401 return;
11402 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011403 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011404 + r.curComponent, e);
11405 }
11406
11407 // If a dead object exception was thrown -- fall through to
11408 // restart the application.
11409 }
11410
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011411 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011412 if (DEBUG_BROADCAST) Slog.v(TAG,
11413 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011414 if ((r.curApp=startProcessLocked(targetProcess,
11415 info.activityInfo.applicationInfo, true,
11416 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011417 "broadcast", r.curComponent,
11418 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11419 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011420 // Ah, this recipient is unavailable. Finish it if necessary,
11421 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011422 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011423 + info.activityInfo.applicationInfo.packageName + "/"
11424 + info.activityInfo.applicationInfo.uid + " for broadcast "
11425 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011426 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011427 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11428 r.resultExtras, r.resultAbort, true);
11429 scheduleBroadcastsLocked();
11430 r.state = BroadcastRecord.IDLE;
11431 return;
11432 }
11433
11434 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011435 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 }
11437 }
11438
11439 // =========================================================
11440 // INSTRUMENTATION
11441 // =========================================================
11442
11443 public boolean startInstrumentation(ComponentName className,
11444 String profileFile, int flags, Bundle arguments,
11445 IInstrumentationWatcher watcher) {
11446 // Refuse possible leaked file descriptors
11447 if (arguments != null && arguments.hasFileDescriptors()) {
11448 throw new IllegalArgumentException("File descriptors passed in Bundle");
11449 }
11450
11451 synchronized(this) {
11452 InstrumentationInfo ii = null;
11453 ApplicationInfo ai = null;
11454 try {
11455 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011456 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011457 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011458 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011459 } catch (PackageManager.NameNotFoundException e) {
11460 }
11461 if (ii == null) {
11462 reportStartInstrumentationFailure(watcher, className,
11463 "Unable to find instrumentation info for: " + className);
11464 return false;
11465 }
11466 if (ai == null) {
11467 reportStartInstrumentationFailure(watcher, className,
11468 "Unable to find instrumentation target package: " + ii.targetPackage);
11469 return false;
11470 }
11471
11472 int match = mContext.getPackageManager().checkSignatures(
11473 ii.targetPackage, ii.packageName);
11474 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11475 String msg = "Permission Denial: starting instrumentation "
11476 + className + " from pid="
11477 + Binder.getCallingPid()
11478 + ", uid=" + Binder.getCallingPid()
11479 + " not allowed because package " + ii.packageName
11480 + " does not have a signature matching the target "
11481 + ii.targetPackage;
11482 reportStartInstrumentationFailure(watcher, className, msg);
11483 throw new SecurityException(msg);
11484 }
11485
11486 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011487 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011488 ProcessRecord app = addAppLocked(ai);
11489 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011490 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011491 app.instrumentationProfileFile = profileFile;
11492 app.instrumentationArguments = arguments;
11493 app.instrumentationWatcher = watcher;
11494 app.instrumentationResultClass = className;
11495 Binder.restoreCallingIdentity(origId);
11496 }
11497
11498 return true;
11499 }
11500
11501 /**
11502 * Report errors that occur while attempting to start Instrumentation. Always writes the
11503 * error to the logs, but if somebody is watching, send the report there too. This enables
11504 * the "am" command to report errors with more information.
11505 *
11506 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11507 * @param cn The component name of the instrumentation.
11508 * @param report The error report.
11509 */
11510 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11511 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011512 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 try {
11514 if (watcher != null) {
11515 Bundle results = new Bundle();
11516 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11517 results.putString("Error", report);
11518 watcher.instrumentationStatus(cn, -1, results);
11519 }
11520 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011521 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011522 }
11523 }
11524
11525 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11526 if (app.instrumentationWatcher != null) {
11527 try {
11528 // NOTE: IInstrumentationWatcher *must* be oneway here
11529 app.instrumentationWatcher.instrumentationFinished(
11530 app.instrumentationClass,
11531 resultCode,
11532 results);
11533 } catch (RemoteException e) {
11534 }
11535 }
11536 app.instrumentationWatcher = null;
11537 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011538 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011539 app.instrumentationProfileFile = null;
11540 app.instrumentationArguments = null;
11541
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011542 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011543 }
11544
11545 public void finishInstrumentation(IApplicationThread target,
11546 int resultCode, Bundle results) {
11547 // Refuse possible leaked file descriptors
11548 if (results != null && results.hasFileDescriptors()) {
11549 throw new IllegalArgumentException("File descriptors passed in Intent");
11550 }
11551
11552 synchronized(this) {
11553 ProcessRecord app = getRecordForAppLocked(target);
11554 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011555 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011556 return;
11557 }
11558 final long origId = Binder.clearCallingIdentity();
11559 finishInstrumentationLocked(app, resultCode, results);
11560 Binder.restoreCallingIdentity(origId);
11561 }
11562 }
11563
11564 // =========================================================
11565 // CONFIGURATION
11566 // =========================================================
11567
11568 public ConfigurationInfo getDeviceConfigurationInfo() {
11569 ConfigurationInfo config = new ConfigurationInfo();
11570 synchronized (this) {
11571 config.reqTouchScreen = mConfiguration.touchscreen;
11572 config.reqKeyboardType = mConfiguration.keyboard;
11573 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011574 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11575 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11577 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011578 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11579 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011580 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11581 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011582 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011583 }
11584 return config;
11585 }
11586
11587 public Configuration getConfiguration() {
11588 Configuration ci;
11589 synchronized(this) {
11590 ci = new Configuration(mConfiguration);
11591 }
11592 return ci;
11593 }
11594
11595 public void updateConfiguration(Configuration values) {
11596 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11597 "updateConfiguration()");
11598
11599 synchronized(this) {
11600 if (values == null && mWindowManager != null) {
11601 // sentinel: fetch the current configuration from the window manager
11602 values = mWindowManager.computeNewConfiguration();
11603 }
11604
11605 final long origId = Binder.clearCallingIdentity();
11606 updateConfigurationLocked(values, null);
11607 Binder.restoreCallingIdentity(origId);
11608 }
11609 }
11610
11611 /**
11612 * Do either or both things: (1) change the current configuration, and (2)
11613 * make sure the given activity is running with the (now) current
11614 * configuration. Returns true if the activity has been left running, or
11615 * false if <var>starting</var> is being destroyed to match the new
11616 * configuration.
11617 */
11618 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011619 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620 int changes = 0;
11621
11622 boolean kept = true;
11623
11624 if (values != null) {
11625 Configuration newConfig = new Configuration(mConfiguration);
11626 changes = newConfig.updateFrom(values);
11627 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011628 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011629 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011630 }
11631
Doug Zongker2bec3d42009-12-04 12:52:44 -080011632 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633
11634 if (values.locale != null) {
11635 saveLocaleLocked(values.locale,
11636 !values.locale.equals(mConfiguration.locale),
11637 values.userSetLocale);
11638 }
11639
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011640 mConfigurationSeq++;
11641 if (mConfigurationSeq <= 0) {
11642 mConfigurationSeq = 1;
11643 }
11644 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011645 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011646 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011647
11648 AttributeCache ac = AttributeCache.instance();
11649 if (ac != null) {
11650 ac.updateConfiguration(mConfiguration);
11651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011652
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011653 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11654 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11655 msg.obj = new Configuration(mConfiguration);
11656 mHandler.sendMessage(msg);
11657 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011658
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011659 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11660 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011661 try {
11662 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011663 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011664 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011665 app.thread.scheduleConfigurationChanged(mConfiguration);
11666 }
11667 } catch (Exception e) {
11668 }
11669 }
11670 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011671 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11672 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11674 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011675 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11676 broadcastIntentLocked(null, null,
11677 new Intent(Intent.ACTION_LOCALE_CHANGED),
11678 null, null, 0, null, null,
11679 null, false, false, MY_PID, Process.SYSTEM_UID);
11680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011681 }
11682 }
11683
11684 if (changes != 0 && starting == null) {
11685 // If the configuration changed, and the caller is not already
11686 // in the process of starting an activity, then find the top
11687 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011688 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011689 }
11690
11691 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011692 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011693 if (kept) {
11694 // If this didn't result in the starting activity being
11695 // destroyed, then we need to make sure at this point that all
11696 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011697 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011698 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011699 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011700 }
11701 }
11702
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011703 if (values != null && mWindowManager != null) {
11704 mWindowManager.setNewConfiguration(mConfiguration);
11705 }
11706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011707 return kept;
11708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011709
11710 /**
11711 * Save the locale. You must be inside a synchronized (this) block.
11712 */
11713 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11714 if(isDiff) {
11715 SystemProperties.set("user.language", l.getLanguage());
11716 SystemProperties.set("user.region", l.getCountry());
11717 }
11718
11719 if(isPersist) {
11720 SystemProperties.set("persist.sys.language", l.getLanguage());
11721 SystemProperties.set("persist.sys.country", l.getCountry());
11722 SystemProperties.set("persist.sys.localevar", l.getVariant());
11723 }
11724 }
11725
11726 // =========================================================
11727 // LIFETIME MANAGEMENT
11728 // =========================================================
11729
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011730 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11731 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011732 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011733 // This adjustment has already been computed. If we are calling
11734 // from the top, we may have already computed our adjustment with
11735 // an earlier hidden adjustment that isn't really for us... if
11736 // so, use the new hidden adjustment.
11737 if (!recursed && app.hidden) {
11738 app.curAdj = hiddenAdj;
11739 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011740 return app.curAdj;
11741 }
11742
11743 if (app.thread == null) {
11744 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011745 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011746 return (app.curAdj=EMPTY_APP_ADJ);
11747 }
11748
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011749 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11750 // The max adjustment doesn't allow this app to be anything
11751 // below foreground, so it is not worth doing work for it.
11752 app.adjType = "fixed";
11753 app.adjSeq = mAdjSeq;
11754 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011755 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011756 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11757 return (app.curAdj=app.maxAdj);
11758 }
11759
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011760 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011761 app.adjSource = null;
11762 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011763 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011764 app.empty = false;
11765 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011766
The Android Open Source Project4df24232009-03-05 14:34:35 -080011767 // Determine the importance of the process, starting with most
11768 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011769 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011770 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011772 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011773 // The last app on the list is the foreground app.
11774 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011775 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011776 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011777 } else if (app.instrumentationClass != null) {
11778 // Don't want to kill running instrumentation.
11779 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011780 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011781 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011782 } else if (app.curReceiver != null ||
11783 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11784 // An app that is currently receiving a broadcast also
11785 // counts as being in the foreground.
11786 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011787 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011788 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011789 } else if (app.executingServices.size() > 0) {
11790 // An app that is currently executing a service callback also
11791 // counts as being in the foreground.
11792 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011793 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011794 app.adjType = "exec-service";
11795 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011796 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011797 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011798 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011799 app.adjType = "foreground-service";
11800 } else if (app.forcingToForeground != null) {
11801 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011802 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011803 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011804 app.adjType = "force-foreground";
11805 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011806 } else if (app == mHeavyWeightProcess) {
11807 // We don't want to kill the current heavy-weight process.
11808 adj = HEAVY_WEIGHT_APP_ADJ;
11809 schedGroup = Process.THREAD_GROUP_DEFAULT;
11810 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011811 } else if (app == mHomeProcess) {
11812 // This process is hosting what we currently consider to be the
11813 // home app, so we don't want to let it go into the background.
11814 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011815 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011816 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011817 } else if ((N=app.activities.size()) != 0) {
11818 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011819 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011820 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011821 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011822 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011823 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011824 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011825 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011826 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011827 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011828 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011829 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011830 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011831 break;
11832 }
11833 }
11834 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011835 // A very not-needed process. If this is lower in the lru list,
11836 // we will push it in to the empty bucket.
11837 app.hidden = true;
11838 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011839 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011840 adj = hiddenAdj;
11841 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011842 }
11843
Joe Onorato8a9b2202010-02-26 18:56:32 -080011844 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011845
The Android Open Source Project4df24232009-03-05 14:34:35 -080011846 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011847 // there are applications dependent on our services or providers, but
11848 // this gives us a baseline and makes sure we don't get into an
11849 // infinite recursion.
11850 app.adjSeq = mAdjSeq;
11851 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011852
Christopher Tate6fa95972009-06-05 18:43:55 -070011853 if (mBackupTarget != null && app == mBackupTarget.app) {
11854 // If possible we want to avoid killing apps while they're being backed up
11855 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011856 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011857 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011858 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011859 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011860 }
11861 }
11862
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011863 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11864 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011865 final long now = SystemClock.uptimeMillis();
11866 // This process is more important if the top activity is
11867 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011868 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011869 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011870 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011871 if (s.startRequested) {
11872 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11873 // This service has seen some activity within
11874 // recent memory, so we will keep its process ahead
11875 // of the background processes.
11876 if (adj > SECONDARY_SERVER_ADJ) {
11877 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011878 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011879 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011880 }
11881 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011882 // If we have let the service slide into the background
11883 // state, still have some text describing what it is doing
11884 // even though the service no longer has an impact.
11885 if (adj > SECONDARY_SERVER_ADJ) {
11886 app.adjType = "started-bg-services";
11887 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011888 // Don't kill this process because it is doing work; it
11889 // has said it is doing work.
11890 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011891 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011892 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11893 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011894 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011895 = s.connections.values().iterator();
11896 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011897 ArrayList<ConnectionRecord> clist = kt.next();
11898 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11899 // XXX should compute this based on the max of
11900 // all connected clients.
11901 ConnectionRecord cr = clist.get(i);
11902 if (cr.binding.client == app) {
11903 // Binding to ourself is not interesting.
11904 continue;
11905 }
11906 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11907 ProcessRecord client = cr.binding.client;
11908 int myHiddenAdj = hiddenAdj;
11909 if (myHiddenAdj > client.hiddenAdj) {
11910 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11911 myHiddenAdj = client.hiddenAdj;
11912 } else {
11913 myHiddenAdj = VISIBLE_APP_ADJ;
11914 }
11915 }
11916 int clientAdj = computeOomAdjLocked(
11917 client, myHiddenAdj, TOP_APP, true);
11918 if (adj > clientAdj) {
11919 adj = clientAdj >= VISIBLE_APP_ADJ
11920 ? clientAdj : VISIBLE_APP_ADJ;
11921 if (!client.hidden) {
11922 app.hidden = false;
11923 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011924 if (client.keeping) {
11925 app.keeping = true;
11926 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011927 app.adjType = "service";
11928 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11929 .REASON_SERVICE_IN_USE;
11930 app.adjSource = cr.binding.client;
11931 app.adjTarget = s.name;
11932 }
11933 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11934 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11935 schedGroup = Process.THREAD_GROUP_DEFAULT;
11936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011937 }
11938 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011939 ActivityRecord a = cr.activity;
11940 //if (a != null) {
11941 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11942 //}
11943 if (a != null && adj > FOREGROUND_APP_ADJ &&
11944 (a.state == ActivityState.RESUMED
11945 || a.state == ActivityState.PAUSING)) {
11946 adj = FOREGROUND_APP_ADJ;
11947 schedGroup = Process.THREAD_GROUP_DEFAULT;
11948 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011949 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011950 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11951 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011952 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011953 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011955 }
11956 }
11957 }
11958 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011959
Dianne Hackborn287952c2010-09-22 22:34:31 -070011960 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011961 // would like to avoid killing it unless it would prevent the current
11962 // application from running. By default we put the process in
11963 // with the rest of the background processes; as we scan through
11964 // its services we may bump it up from there.
11965 if (adj > hiddenAdj) {
11966 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011967 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011968 app.adjType = "bg-services";
11969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011970 }
11971
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011972 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11973 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011974 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011975 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11976 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011977 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011978 if (cpr.clients.size() != 0) {
11979 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11980 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11981 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011982 if (client == app) {
11983 // Being our own client is not interesting.
11984 continue;
11985 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011986 int myHiddenAdj = hiddenAdj;
11987 if (myHiddenAdj > client.hiddenAdj) {
11988 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11989 myHiddenAdj = client.hiddenAdj;
11990 } else {
11991 myHiddenAdj = FOREGROUND_APP_ADJ;
11992 }
11993 }
11994 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011995 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011996 if (adj > clientAdj) {
11997 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011998 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011999 if (!client.hidden) {
12000 app.hidden = false;
12001 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012002 if (client.keeping) {
12003 app.keeping = true;
12004 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012005 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012006 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12007 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012008 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012009 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012010 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012011 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12012 schedGroup = Process.THREAD_GROUP_DEFAULT;
12013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012014 }
12015 }
12016 // If the provider has external (non-framework) process
12017 // dependencies, ensure that its adjustment is at least
12018 // FOREGROUND_APP_ADJ.
12019 if (cpr.externals != 0) {
12020 if (adj > FOREGROUND_APP_ADJ) {
12021 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012022 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012023 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012024 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012025 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012026 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012027 }
12028 }
12029 }
12030 }
12031
12032 app.curRawAdj = adj;
12033
Joe Onorato8a9b2202010-02-26 18:56:32 -080012034 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012035 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12036 if (adj > app.maxAdj) {
12037 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012038 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012039 schedGroup = Process.THREAD_GROUP_DEFAULT;
12040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012041 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012042 if (adj < HIDDEN_APP_MIN_ADJ) {
12043 app.keeping = true;
12044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012045
12046 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012047 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012049 return adj;
12050 }
12051
12052 /**
12053 * Ask a given process to GC right now.
12054 */
12055 final void performAppGcLocked(ProcessRecord app) {
12056 try {
12057 app.lastRequestedGc = SystemClock.uptimeMillis();
12058 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012059 if (app.reportLowMemory) {
12060 app.reportLowMemory = false;
12061 app.thread.scheduleLowMemory();
12062 } else {
12063 app.thread.processInBackground();
12064 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012065 }
12066 } catch (Exception e) {
12067 // whatever.
12068 }
12069 }
12070
12071 /**
12072 * Returns true if things are idle enough to perform GCs.
12073 */
Josh Bartel7f208742010-02-25 11:01:44 -060012074 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012075 return mParallelBroadcasts.size() == 0
12076 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012077 && (mSleeping || (mMainStack.mResumedActivity != null &&
12078 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012079 }
12080
12081 /**
12082 * Perform GCs on all processes that are waiting for it, but only
12083 * if things are idle.
12084 */
12085 final void performAppGcsLocked() {
12086 final int N = mProcessesToGc.size();
12087 if (N <= 0) {
12088 return;
12089 }
Josh Bartel7f208742010-02-25 11:01:44 -060012090 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012091 while (mProcessesToGc.size() > 0) {
12092 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012093 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012094 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12095 <= SystemClock.uptimeMillis()) {
12096 // To avoid spamming the system, we will GC processes one
12097 // at a time, waiting a few seconds between each.
12098 performAppGcLocked(proc);
12099 scheduleAppGcsLocked();
12100 return;
12101 } else {
12102 // It hasn't been long enough since we last GCed this
12103 // process... put it in the list to wait for its time.
12104 addProcessToGcListLocked(proc);
12105 break;
12106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012107 }
12108 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012109
12110 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012111 }
12112 }
12113
12114 /**
12115 * If all looks good, perform GCs on all processes waiting for them.
12116 */
12117 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012118 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012119 performAppGcsLocked();
12120 return;
12121 }
12122 // Still not idle, wait some more.
12123 scheduleAppGcsLocked();
12124 }
12125
12126 /**
12127 * Schedule the execution of all pending app GCs.
12128 */
12129 final void scheduleAppGcsLocked() {
12130 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012131
12132 if (mProcessesToGc.size() > 0) {
12133 // Schedule a GC for the time to the next process.
12134 ProcessRecord proc = mProcessesToGc.get(0);
12135 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12136
12137 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12138 long now = SystemClock.uptimeMillis();
12139 if (when < (now+GC_TIMEOUT)) {
12140 when = now + GC_TIMEOUT;
12141 }
12142 mHandler.sendMessageAtTime(msg, when);
12143 }
12144 }
12145
12146 /**
12147 * Add a process to the array of processes waiting to be GCed. Keeps the
12148 * list in sorted order by the last GC time. The process can't already be
12149 * on the list.
12150 */
12151 final void addProcessToGcListLocked(ProcessRecord proc) {
12152 boolean added = false;
12153 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12154 if (mProcessesToGc.get(i).lastRequestedGc <
12155 proc.lastRequestedGc) {
12156 added = true;
12157 mProcessesToGc.add(i+1, proc);
12158 break;
12159 }
12160 }
12161 if (!added) {
12162 mProcessesToGc.add(0, proc);
12163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012164 }
12165
12166 /**
12167 * Set up to ask a process to GC itself. This will either do it
12168 * immediately, or put it on the list of processes to gc the next
12169 * time things are idle.
12170 */
12171 final void scheduleAppGcLocked(ProcessRecord app) {
12172 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012173 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012174 return;
12175 }
12176 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012177 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012178 scheduleAppGcsLocked();
12179 }
12180 }
12181
Dianne Hackborn287952c2010-09-22 22:34:31 -070012182 final void checkExcessivePowerUsageLocked(boolean doKills) {
12183 updateCpuStatsNow();
12184
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012185 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012186 boolean doWakeKills = doKills;
12187 boolean doCpuKills = doKills;
12188 if (mLastPowerCheckRealtime == 0) {
12189 doWakeKills = false;
12190 }
12191 if (mLastPowerCheckUptime == 0) {
12192 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012193 }
12194 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012195 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012196 }
12197 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012198 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12199 final long curUptime = SystemClock.uptimeMillis();
12200 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12201 mLastPowerCheckRealtime = curRealtime;
12202 mLastPowerCheckUptime = curUptime;
12203 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12204 doWakeKills = false;
12205 }
12206 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12207 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012208 }
12209 int i = mLruProcesses.size();
12210 while (i > 0) {
12211 i--;
12212 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012213 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012214 long wtime;
12215 synchronized (stats) {
12216 wtime = stats.getProcessWakeTime(app.info.uid,
12217 app.pid, curRealtime);
12218 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012219 long wtimeUsed = wtime - app.lastWakeTime;
12220 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12221 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012222 StringBuilder sb = new StringBuilder(128);
12223 sb.append("Wake for ");
12224 app.toShortString(sb);
12225 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012226 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012227 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012228 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012229 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012230 sb.append((wtimeUsed*100)/realtimeSince);
12231 sb.append("%)");
12232 Slog.i(TAG, sb.toString());
12233 sb.setLength(0);
12234 sb.append("CPU for ");
12235 app.toShortString(sb);
12236 sb.append(": over ");
12237 TimeUtils.formatDuration(uptimeSince, sb);
12238 sb.append(" used ");
12239 TimeUtils.formatDuration(cputimeUsed, sb);
12240 sb.append(" (");
12241 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012242 sb.append("%)");
12243 Slog.i(TAG, sb.toString());
12244 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012245 // If a process has held a wake lock for more
12246 // than 50% of the time during this period,
12247 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012248 if (doWakeKills && realtimeSince > 0
12249 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12250 synchronized (stats) {
12251 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12252 realtimeSince, wtimeUsed);
12253 }
12254 Slog.w(TAG, "Excessive wake lock in " + app.processName
12255 + " (pid " + app.pid + "): held " + wtimeUsed
12256 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012257 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12258 app.processName, app.setAdj, "excessive wake lock");
12259 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012260 } else if (doCpuKills && uptimeSince > 0
12261 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12262 synchronized (stats) {
12263 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12264 uptimeSince, cputimeUsed);
12265 }
12266 Slog.w(TAG, "Excessive CPU in " + app.processName
12267 + " (pid " + app.pid + "): used " + cputimeUsed
12268 + " during " + uptimeSince);
12269 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12270 app.processName, app.setAdj, "excessive cpu");
12271 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012272 } else {
12273 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012274 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012275 }
12276 }
12277 }
12278 }
12279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012280 private final boolean updateOomAdjLocked(
12281 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12282 app.hiddenAdj = hiddenAdj;
12283
12284 if (app.thread == null) {
12285 return true;
12286 }
12287
Dianne Hackborn287952c2010-09-22 22:34:31 -070012288 final boolean wasKeeping = app.keeping;
12289
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012290 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012291
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012292 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012293 if (app.curRawAdj != app.setRawAdj) {
12294 if (app.curRawAdj > FOREGROUND_APP_ADJ
12295 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12296 // If this app is transitioning from foreground to
12297 // non-foreground, have it do a gc.
12298 scheduleAppGcLocked(app);
12299 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12300 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12301 // Likewise do a gc when an app is moving in to the
12302 // background (such as a service stopping).
12303 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012304 }
12305
12306 if (wasKeeping && !app.keeping) {
12307 // This app is no longer something we want to keep. Note
12308 // its current wake lock time to later know to kill it if
12309 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012310 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12311 synchronized (stats) {
12312 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12313 app.pid, SystemClock.elapsedRealtime());
12314 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012315 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012316 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012318 app.setRawAdj = app.curRawAdj;
12319 }
12320 if (adj != app.setAdj) {
12321 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012322 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012323 TAG, "Set app " + app.processName +
12324 " oom adj to " + adj);
12325 app.setAdj = adj;
12326 } else {
12327 return false;
12328 }
12329 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012330 if (app.setSchedGroup != app.curSchedGroup) {
12331 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012332 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012333 "Setting process group of " + app.processName
12334 + " to " + app.curSchedGroup);
12335 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012336 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012337 try {
12338 Process.setProcessGroup(app.pid, app.curSchedGroup);
12339 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012340 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012341 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012342 e.printStackTrace();
12343 } finally {
12344 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012345 }
12346 }
12347 if (false) {
12348 if (app.thread != null) {
12349 try {
12350 app.thread.setSchedulingGroup(app.curSchedGroup);
12351 } catch (RemoteException e) {
12352 }
12353 }
12354 }
12355 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012356 }
12357
12358 return true;
12359 }
12360
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012361 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012362 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012363 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012364 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012365 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012366 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012367 }
12368 }
12369 return resumedActivity;
12370 }
12371
12372 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012373 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012374 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12375 int curAdj = app.curAdj;
12376 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12377 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12378
12379 mAdjSeq++;
12380
12381 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12382 if (res) {
12383 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12384 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12385 if (nowHidden != wasHidden) {
12386 // Changed to/from hidden state, so apps after it in the LRU
12387 // list may also be changed.
12388 updateOomAdjLocked();
12389 }
12390 }
12391 return res;
12392 }
12393
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012394 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012395 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012396 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012397 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12398
12399 if (false) {
12400 RuntimeException e = new RuntimeException();
12401 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012402 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012403 }
12404
12405 mAdjSeq++;
12406
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012407 // Let's determine how many processes we have running vs.
12408 // how many slots we have for background processes; we may want
12409 // to put multiple processes in a slot of there are enough of
12410 // them.
12411 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12412 int factor = (mLruProcesses.size()-4)/numSlots;
12413 if (factor < 1) factor = 1;
12414 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012415 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012417 // First try updating the OOM adjustment for each of the
12418 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012419 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012420 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12421 while (i > 0) {
12422 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012423 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012424 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012425 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012426 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012427 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012428 step++;
12429 if (step >= factor) {
12430 step = 0;
12431 curHiddenAdj++;
12432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012433 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012434 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012435 if (!app.killedBackground) {
12436 numHidden++;
12437 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012438 Slog.i(TAG, "No longer want " + app.processName
12439 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012440 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12441 app.processName, app.setAdj, "too many background");
12442 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012443 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012444 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012445 }
12446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012447 } else {
12448 didOomAdj = false;
12449 }
12450 }
12451
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012452 // If we return false, we will fall back on killing processes to
12453 // have a fixed limit. Do this if a limit has been requested; else
12454 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012455 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12456 }
12457
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012458 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012459 synchronized (this) {
12460 int i;
12461
12462 // First remove any unused application processes whose package
12463 // has been removed.
12464 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12465 final ProcessRecord app = mRemovedProcesses.get(i);
12466 if (app.activities.size() == 0
12467 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012468 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012469 TAG, "Exiting empty application process "
12470 + app.processName + " ("
12471 + (app.thread != null ? app.thread.asBinder() : null)
12472 + ")\n");
12473 if (app.pid > 0 && app.pid != MY_PID) {
12474 Process.killProcess(app.pid);
12475 } else {
12476 try {
12477 app.thread.scheduleExit();
12478 } catch (Exception e) {
12479 // Ignore exceptions.
12480 }
12481 }
12482 cleanUpApplicationRecordLocked(app, false, -1);
12483 mRemovedProcesses.remove(i);
12484
12485 if (app.persistent) {
12486 if (app.persistent) {
12487 addAppLocked(app.info);
12488 }
12489 }
12490 }
12491 }
12492
12493 // Now try updating the OOM adjustment for each of the
12494 // application processes based on their current state.
12495 // If the setOomAdj() API is not supported, then go with our
12496 // back-up plan...
12497 if (!updateOomAdjLocked()) {
12498
12499 // Count how many processes are running services.
12500 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012501 for (i=mLruProcesses.size()-1; i>=0; i--) {
12502 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012503
12504 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012505 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012506 // Don't count processes holding services against our
12507 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012508 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012509 TAG, "Not trimming app " + app + " with services: "
12510 + app.services);
12511 numServiceProcs++;
12512 }
12513 }
12514
12515 int curMaxProcs = mProcessLimit;
12516 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12517 if (mAlwaysFinishActivities) {
12518 curMaxProcs = 1;
12519 }
12520 curMaxProcs += numServiceProcs;
12521
12522 // Quit as many processes as we can to get down to the desired
12523 // process count. First remove any processes that no longer
12524 // have activites running in them.
12525 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012526 i<mLruProcesses.size()
12527 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012528 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012529 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012530 // Quit an application only if it is not currently
12531 // running any activities.
12532 if (!app.persistent && app.activities.size() == 0
12533 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012534 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012535 TAG, "Exiting empty application process "
12536 + app.processName + " ("
12537 + (app.thread != null ? app.thread.asBinder() : null)
12538 + ")\n");
12539 if (app.pid > 0 && app.pid != MY_PID) {
12540 Process.killProcess(app.pid);
12541 } else {
12542 try {
12543 app.thread.scheduleExit();
12544 } catch (Exception e) {
12545 // Ignore exceptions.
12546 }
12547 }
12548 // todo: For now we assume the application is not buggy
12549 // or evil, and will quit as a result of our request.
12550 // Eventually we need to drive this off of the death
12551 // notification, and kill the process if it takes too long.
12552 cleanUpApplicationRecordLocked(app, false, i);
12553 i--;
12554 }
12555 }
12556
12557 // If we still have too many processes, now from the least
12558 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012559 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012560 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012561 " of " + curMaxProcs + " processes");
12562 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012563 i<mLruProcesses.size()
12564 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012565 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012566 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012567 // Quit the application only if we have a state saved for
12568 // all of its activities.
12569 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012570 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012571 int NUMA = app.activities.size();
12572 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012573 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012574 TAG, "Looking to quit " + app.processName);
12575 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012576 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012577 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578 TAG, " " + r.intent.getComponent().flattenToShortString()
12579 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12580 canQuit = (r.haveState || !r.stateNotNeeded)
12581 && !r.visible && r.stopped;
12582 }
12583 if (canQuit) {
12584 // Finish all of the activities, and then the app itself.
12585 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012586 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012587 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012588 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012589 }
12590 r.resultTo = null;
12591 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012592 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012593 + app.processName + " ("
12594 + (app.thread != null ? app.thread.asBinder() : null)
12595 + ")\n");
12596 if (app.pid > 0 && app.pid != MY_PID) {
12597 Process.killProcess(app.pid);
12598 } else {
12599 try {
12600 app.thread.scheduleExit();
12601 } catch (Exception e) {
12602 // Ignore exceptions.
12603 }
12604 }
12605 // todo: For now we assume the application is not buggy
12606 // or evil, and will quit as a result of our request.
12607 // Eventually we need to drive this off of the death
12608 // notification, and kill the process if it takes too long.
12609 cleanUpApplicationRecordLocked(app, false, i);
12610 i--;
12611 //dump();
12612 }
12613 }
12614
12615 }
12616
12617 int curMaxActivities = MAX_ACTIVITIES;
12618 if (mAlwaysFinishActivities) {
12619 curMaxActivities = 1;
12620 }
12621
12622 // Finally, if there are too many activities now running, try to
12623 // finish as many as we can to get back down to the limit.
12624 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012625 i<mMainStack.mLRUActivities.size()
12626 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012627 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012628 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012629 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012630
12631 // We can finish this one if we have its icicle saved and
12632 // it is not persistent.
12633 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012634 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012635 final int origSize = mMainStack.mLRUActivities.size();
12636 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012637
12638 // This will remove it from the LRU list, so keep
12639 // our index at the same value. Note that this check to
12640 // see if the size changes is just paranoia -- if
12641 // something unexpected happens, we don't want to end up
12642 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012643 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012644 i--;
12645 }
12646 }
12647 }
12648 }
12649 }
12650
12651 /** This method sends the specified signal to each of the persistent apps */
12652 public void signalPersistentProcesses(int sig) throws RemoteException {
12653 if (sig != Process.SIGNAL_USR1) {
12654 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12655 }
12656
12657 synchronized (this) {
12658 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12659 != PackageManager.PERMISSION_GRANTED) {
12660 throw new SecurityException("Requires permission "
12661 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12662 }
12663
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012664 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12665 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012666 if (r.thread != null && r.persistent) {
12667 Process.sendSignal(r.pid, sig);
12668 }
12669 }
12670 }
12671 }
12672
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012673 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012674 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012675
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012676 try {
12677 synchronized (this) {
12678 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12679 // its own permission.
12680 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12681 != PackageManager.PERMISSION_GRANTED) {
12682 throw new SecurityException("Requires permission "
12683 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012684 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012685
12686 if (start && fd == null) {
12687 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012688 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012689
12690 ProcessRecord proc = null;
12691 try {
12692 int pid = Integer.parseInt(process);
12693 synchronized (mPidsSelfLocked) {
12694 proc = mPidsSelfLocked.get(pid);
12695 }
12696 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012697 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012698
12699 if (proc == null) {
12700 HashMap<String, SparseArray<ProcessRecord>> all
12701 = mProcessNames.getMap();
12702 SparseArray<ProcessRecord> procs = all.get(process);
12703 if (procs != null && procs.size() > 0) {
12704 proc = procs.valueAt(0);
12705 }
12706 }
12707
12708 if (proc == null || proc.thread == null) {
12709 throw new IllegalArgumentException("Unknown process: " + process);
12710 }
12711
12712 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12713 if (isSecure) {
12714 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12715 throw new SecurityException("Process not debuggable: " + proc);
12716 }
12717 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012718
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012719 proc.thread.profilerControl(start, path, fd);
12720 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012721 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012722 }
12723 } catch (RemoteException e) {
12724 throw new IllegalStateException("Process disappeared");
12725 } finally {
12726 if (fd != null) {
12727 try {
12728 fd.close();
12729 } catch (IOException e) {
12730 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012731 }
12732 }
12733 }
Andy McFadden824c5102010-07-09 16:26:57 -070012734
12735 public boolean dumpHeap(String process, boolean managed,
12736 String path, ParcelFileDescriptor fd) throws RemoteException {
12737
12738 try {
12739 synchronized (this) {
12740 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12741 // its own permission (same as profileControl).
12742 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12743 != PackageManager.PERMISSION_GRANTED) {
12744 throw new SecurityException("Requires permission "
12745 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12746 }
12747
12748 if (fd == null) {
12749 throw new IllegalArgumentException("null fd");
12750 }
12751
12752 ProcessRecord proc = null;
12753 try {
12754 int pid = Integer.parseInt(process);
12755 synchronized (mPidsSelfLocked) {
12756 proc = mPidsSelfLocked.get(pid);
12757 }
12758 } catch (NumberFormatException e) {
12759 }
12760
12761 if (proc == null) {
12762 HashMap<String, SparseArray<ProcessRecord>> all
12763 = mProcessNames.getMap();
12764 SparseArray<ProcessRecord> procs = all.get(process);
12765 if (procs != null && procs.size() > 0) {
12766 proc = procs.valueAt(0);
12767 }
12768 }
12769
12770 if (proc == null || proc.thread == null) {
12771 throw new IllegalArgumentException("Unknown process: " + process);
12772 }
12773
12774 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12775 if (isSecure) {
12776 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12777 throw new SecurityException("Process not debuggable: " + proc);
12778 }
12779 }
12780
12781 proc.thread.dumpHeap(managed, path, fd);
12782 fd = null;
12783 return true;
12784 }
12785 } catch (RemoteException e) {
12786 throw new IllegalStateException("Process disappeared");
12787 } finally {
12788 if (fd != null) {
12789 try {
12790 fd.close();
12791 } catch (IOException e) {
12792 }
12793 }
12794 }
12795 }
12796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012797 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12798 public void monitor() {
12799 synchronized (this) { }
12800 }
12801}